原型和对象包装器如何在JavaScript中工作?

时间:2017-09-18 02:02:01

标签: javascript object prototype

我用几句话写下了我所学到的内容,以真正理解原型和对象包装器是如何工作的。如果我错了请纠正我,如果我遗漏了其他细节,请告诉我。

JavaScript使用原型来查找对象的方法和属性。例如,如果您创建一个字符串"Hello",它是一个原始字符串值并尝试在其上应用方法split()"Hello".split()),字符串值将被强制转换为String对象,因此我们可以应用split()方法。此String对象由String.prototype.constructor创建。创建它之后,JavaScript会在原型对象中查找split()方法。在应用该方法并返回值之后,不再需要String对象,因此它被牺牲给了垃圾收集之神。

1 个答案:

答案 0 :(得分:2)

你本质上是正确的,虽然堆栈空间和继承是两个不同的问题,并且在像js这样的高级脚本语言中,垃圾收集的工作原理可能是不确定的。确实如此,在该行完成后,单个代码行的中间值将被销毁。

此外,String.prototype.constructorString本身相同。 String的任何“实例”都会收到.__proto__引用,该引用将指向String.prototype,从而创建一个继承链。如果发现对象属性未定义为对象x本身,则JavaScript会自动检查x.__proto__引用的对象,然后x.__proto__.__proto__,一直到 - 在大多数情况下 - Object.prototype

请记住,__proto__在JavaScript解释器之间的实现方式不同,不应手动操作。很高兴知道存在这样的参考来解释原型魔法,但是在任何情况下都不应该直接更改对象的__proto__引用。相反,您应该通过new运算符或Object.create创建类的实例。 JavaScript中的完整超级/子类关系如下所示:

function Animal( name, weight ){
    this.name = name, this.weight = weight;
    this.alive = true;
    this.hungry = true;
}

// At this point you could put in Animal.prototype = Object.create(Object.prototype); but JavaScript will set it automatically, so it’s unnecessary

Animal.prototype.kill = function(){
    this.alive = false;
}

Animal.prototype.feed = function(){
    this.hungry = false;
}

function Cat(name, weight){
    Animal.call(this, name, weight);
    this.lives = 9;
}


// Sometimes people instance a new parent like
// Cat.prototype = new Animal('doesntmatter', 420);
// The result is the same except that using Object.create saves the overhead
// of running a full constructor for an object that doesn’t need it
Cat.prototype = Object.create(Animal.prototype);

Cat.prototype.kill = function(){
    this.lives--;
    if(this.lives <= 0) this.alive = false;
};


var a = new Animal();
var c = new Cat();

/* a.feed and b.feed now reference the same function object,
but c.kill has been overridden since its prototype `__proto__` chain first 
visits Cat.prototype, then Animal.prototype, then Object.prototype. */

最后,ES6引入了一个class关键字,它是该系统的语法糖,并将构造函数抽象为init方法。