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

时间:2016-10-11 02:54:12

标签: 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 = 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呢?

2 个答案:

答案 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