Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/461.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将方法添加到Javascript原型和将功能添加到现有对象之间有什么区别_Javascript_Oop - Fatal编程技术网

将方法添加到Javascript原型和将功能添加到现有对象之间有什么区别

将方法添加到Javascript原型和将功能添加到现有对象之间有什么区别,javascript,oop,Javascript,Oop,我在一本书中读到,我们可以使用以下代码扩展现有对象的功能: var Point = function(x, y) { this.x = x; this.y = y; } Point.prototype.moveBy = function(deltaX, deltaY) { this.x += deltaX; this.y += deltaY; } Point.prototype.moveTo = function(otherPoint) { this.x

我在一本书中读到,我们可以使用以下代码扩展现有对象的功能:

var Point = function(x, y) {
    this.x = x; 
  this.y = y; 
}

Point.prototype.moveBy = function(deltaX, deltaY) {
    this.x += deltaX; 
  this.y += deltaY; 
}
Point.prototype.moveTo = function(otherPoint) {
    this.x = otherPoint.x; 
  this.y = otherPoint.y; 
}
var p1= new Point(100, 200); 
p1.moveBy(10, 20); 
var p2= new Point(25, 50); 
p2.moveTo(p1); 
alert("p2.x: " + p2.x + " p2.y: " + p2.y); 
我刚刚发现,我可以用prototype获得如下相同的结果:

var Point = function(x, y) {
    this.x = x; 
  this.y = y; 
}

Point.prototype = {
    moveBy: function(deltaX, deltaY) {
    this.x += deltaX; 
  this.y += deltaY; 
    }, 

    moveTo: function(otherPoint) {
    this.x = otherPoint.x; 
  this.y = otherPoint.y; 
    }
}; 
var p1= new Point(100, 200); 
p1.moveBy(10, 20); 
var p2= new Point(25, 50); 
p2.moveTo(p1); 
alert("p2.x: " + p2.x + " p2.y: " + p2.y); 
那么有什么区别呢?这对我来说毫无意义。 我们正在向哪个对象添加功能? 如果我们在Point对象中创建函数作为方法,有什么区别?
我们为什么不只用原型呢

差别很明显。随着第一次代码和平,您将为
Point.prototype
声明新成员。但是,在第二个示例中,您将为
Point.prototype
提供一个完整的实现

var p3 = new Point('p3');
p3.moveBy = function() { console.log('from the instance', this.value); };
p3.moveBy === p2.moveBy; //false

var p4 = new Point('p4');
p4.moveBy = function() { console.log('from the instance', this.value) };
p4.moveBy === p3.moveBy; //false
JavaScript中的所有对象都是对象的后代;所有对象 从Object.prototype继承方法和属性,尽管它们 可能被重写(具有空原型的对象除外,即。 创建(空)。例如,其他构造函数的原型 重写构造函数属性并提供它们自己的toString() 方法

对对象原型对象的更改由所有对象通过 原型链接,除非属性和方法符合 更改将沿着原型链进一步覆盖。这 提供一个非常强大但潜在危险的机制 重写或扩展对象行为。


绑定到
Prototype
的成员跨实例共享。该成员只有一个实例

function Point(value) { this.value = value; }
Point.prototype.moveBy = function() { console.log('from the prototype', this.value);};
var p1 = new Point('p1');
var p2 = new Point('p2');
p1.moveBy === p2.moveBy; //true. Same instance of moveBy function
在构造函数内直接设置为
的成员或设置为
的特定实例的成员仅可用于
的特定实例。如果要公开跨
点的所有实例共享的逻辑,最好在
原型上设置它

var p3 = new Point('p3');
p3.moveBy = function() { console.log('from the instance', this.value); };
p3.moveBy === p2.moveBy; //false

var p4 = new Point('p4');
p4.moveBy = function() { console.log('from the instance', this.value) };
p4.moveBy === p3.moveBy; //false
最酷的部分是,即使在实例上声明了原型,您也可以始终访问它。如果是,请将实例作为上下文传递:

Point.prototype.moveBy.call(p3); //will call moveBy set on the prototype. Output: "from the prototype p3"
p3.moveBy(); //will call moveBy set on the instance. Output: from the instance p3

上面的代码片段说明了JavaScript(上下文)和面向对象JavaScript(原型)的基本概念。如果您对该主题感兴趣,请参阅N.Zackas关于该主题的书:

注意,第一种方法允许您在使用
new Point()
创建一些对象之后向原型添加方法,并且所有实例都可以访问新方法。第二种方法是用一个新的对象替换整个原型对象,这不会影响现有的实例<代码>foo.prototype={…};foo.prototype.xxx=这对我来说仍然毫无意义。我在哪里可以看到“扩展现有对象的功能”?这就是你的“现有对象”:点,就像每个javascript对象一样,点的成员上都有一个原型。原型是应用于每个点的实例的类属性。因此,您可以创建将应用于所有Point实例的方法。扩展现有对象的功能就是这个意思。为什么我们不在点对象的第一个位置创建函数作为方法呢?它没有任何问题。你可以选择你想要的任何款式。这最终是一个代码可读性的问题。此外,还要注意避免覆盖现有的原型声明。