我在一本书中读到,我们可以使用以下代码扩展现有对象的功能:
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);
我刚刚发现我可以用原型获得相同的结果如下:
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对象中创建函数作为方法有什么区别? 为什么我们不使用Prototype呢?
答案 0 :(得分:4)
绑定到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
在构造函数中直接设置为this
的成员或设置为Point
的特定实例的成员仅可用于Point
的特定实例。如果您希望公开在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
很酷的部分是,即使您已在实例上声明了prototype
,也可以随时访问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
。如果是,请将实例作为上下文传递:
activate
上面的代码片段说明了JavaScript(上下文)和面向对象的JavaScript(原型)的基本概念。如果您对该主题感兴趣,请查看N. Zackas'关于这个主题的书:https://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404
答案 1 :(得分:2)
差异很明显。通过第一次代码安静,您正在为Point.prototype
声明新成员。但是,在第二个中,您为Point.prototype
提供了完整的实现。
JavaScript中的所有对象都来自Object;所有物体 从Object.prototype继承方法和属性,尽管它们 可以被覆盖(除了具有空原型的Object,即 的Object.create(空))。例如,其他构造函数的原型 覆盖构造函数属性并提供自己的toString() 方法
所有对象都可以看到对象原型对象的更改 原型链接,除非属性和方法受制于那些 在原型链中进一步覆盖了更改。这个 提供了一个非常强大但有潜在危险的机制 覆盖或扩展对象行为。 Object.prototype on MDN