您基本上是正确的,尽管堆栈空间和继承是两个不同的问题,并且在像 js 这样的高级脚本语言中,垃圾收集究竟是如何工作的可能是不确定的。确实,单个代码行的中间值会在该行完成后被销毁。
此外,String.prototype.constructor 将与 String 本身相同。 String 的任何“实例”都会收到一个指向String.prototype 的.__proto__ 引用,从而创建一个继承链。如果发现对象属性不是对象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 方法。