将方法添加到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实例的方法。扩展现有对象的功能就是这个意思。为什么我们不在点对象的第一个位置创建函数作为方法呢?它没有任何问题。你可以选择你想要的任何款式。这最终是一个代码可读性的问题。此外,还要注意避免覆盖现有的原型声明。