function Person(name){ this.name = name; } Person.prototype.age = 10; function Programmer(name){ this.name = name; } Programmer.prototype = new Person(); Programmer.prototype.constructor = Programmer; var p1 = new Programmer('p1'); console.log(p1.age); //10
需要注意的就是constructor的修正。因为我们new一个Person对象出来,它的constructor指向自身的构造函数Person,
所以在Programmer的原型中,这个constructor始终是Person,这与逻辑是不符的,所以必须显式的“纠正”一下这个副作用,让 Programmer原型上的constructor指向自己。
function People(name){ this.name = name; this.age = 11; this.getName = function(){ return this.name; } } function Worker(name){ People.call(this,name); } var w1 = new Worker('w1'); console.log(w1.getName()); //w1 console.log(w1.age); //11
在People构造器中所有的属性和方法都用this关键字定义在了自身,而不是放在它的原型上。在子类Worker中,用call把People 当作函数执行了一下,并传入this作为上下文对象。这样就相当于把People中的所有语句拿过来执行一次,所有属性的定义也都被复制过来了。
同样可以 实现继承。完全与原型无关。
那么这种方式与原型继承有何区别呢?最大的区别就在于原型是一个引用,所有实例都引用一个共享的对象,每次创建出一个实例时,并不会复制原型的 内容,只是用一个指针指过去。而类复制的方法不存在共有的东西,每创建一个对象都把构造器中的代码执行一次,当构造器中的方法较多时,会消耗很多的内存。 而原型继承就不会了,只需一个指针指过去就完了。
由这种工作方式产生的另一个区别就是动态修改,我们知道在原型继承中,只要修改了构造器原型中的值,实例对象也跟着变化。但是类复制就不能了,每个对象都有自己的一份数据,已创建出来的对象不会再受构造器的影响了。
另外还有一点,就是属性的访问速度。类复制的方式,对象的属性都在自身,所以在查找的时候可以立即找到,而原型继承在查找的时候还得顺着原型链向上查找,其访问速度肯定不如类复制的快。