概述
這是我在看JavaScript面向對象編程指南的時候,對constructor和繼承的總結。
關於它們的詳細知識,可以上網查到,所以我只寫那些網上沒有的。
內容
constructor的理解constructor的實際用途constructor的陷阱- 從應用角度理解繼承
- 函數構造器的繼承
- 純對象的繼承
constructor的理解
constructor 屬性是一個指針,指向創建此對象的函數。(可以更改)
constructor的實際用途
看下面這段代碼:
var a,b;
(function(){
function A (arg1,arg2) {
this.a = 1;
this.b=2;
}
A.prototype.log = function () {
console.log(this.a);
}
c = new A();
})()
c.log();
// 1
實例c是用閉包建立的,但是因為A是在閉包里面,所以我們不能直接訪問A。但是如果需要給A添加方法怎么辦呢?方法是用constructor。
c.constructor.prototype.log2 = function () {
console.log(2)
}
c.log2();
// 2
constructor的陷阱
//繼承
Child.prototype = new F();
Child.prototype.constructor = Child;
我們一般在繼承中,要給constructor屬性進行重置,比如上面那段代碼,這是為什么呢?
先來看看一個例子:
function Dog(){this.tail = true;}
var benji = new Dog();
Dog.prototype.say = function(){return 'woof';};
Dog.prototype = {paws:4}
var lucy = new Dog();
benji.constructor.prototype.paws
//4
lucy.constructor.prototype.paws
//undefined
其中,benji和lucy都是Dog()的子對象,但是結果卻不相同。造成這種結果的原因是Dog.prototype = {paws:4}重置了Dog()的原型。(原理不明,貌似和__proto__有關。)
如果在Dog.prototype = {paws:4}后面再加一條語句Dog.prototype.constructor = Dog;結果就一樣了。這也是為什么在繼承中要重置constructor的原因。
從應用角度理解繼承
繼承,就是對父元素的代碼復用。
//父元素是函數構造器
function Parent() {
this.id = 3; //帶this的自身屬性
var od = 5; //不帶this的自身屬性
}
Parent.prototype.ud = 7; //原型屬性
//父元素是純對象
Parent= {id:9};
Parent.prototype.ud = 7;
綜合考慮一下,父元素分為2種:函數構造器和純對象。父元素里面的代碼又分為自身屬性和原型屬性。(方法和屬性差不多,所以只考慮屬性。)
所以我們分別來討論函數構造器和純對象的代碼復用,即屬性繼承。
函數構造器的繼承
- 只繼承原型屬性
很簡單,只需要把父對象的原型賦值給子對象即可。(原型繼承法)
Child.prototype = Parent.prototype;
但是這樣的話,修改子對象的原型會影響父對象的原型,所以我們考慮用閉包。(臨時構造器法)
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
但是如果子對象的prototype本來就有值,所以不能直接進行prototype的賦值。這個時候我們可以直接把屬性拷貝過去。(原型屬性拷貝法)
var p = Parent.prototype;
var c = Child.prototype;
for (i in p) {
c[i] = p[i];
}
當然,還有深拷貝法,這里就不貼代碼了。
- 只繼承自身屬性。
首先想到的就是拷貝法,上面貼過代碼這里就補貼了。但是拷貝法只能繼承父對象中不帶this的自身屬性。
如果想只繼承帶this的自身屬性,可以用構造器借用法。
function Child() {
Parent.apply(this, argument);
}
如果想全部繼承的話,那就只能兩者結合了。
- 同時繼承自身屬性和原型屬性
這個時候,我們第一個想到的就是用new。(原型鏈法)
Child.prototype = new Parent();
需要注意的是,這時子對象僅繼承父對象中帶有this的自身元素,不繼承不帶this的自身元素。
其它方法就只能結合上面多個方法了。
純對象的繼承
- 只繼承原型屬性。
和函數構造器的繼承一樣。
- 只繼承自身屬性。
當父元素是純對象的時候,它里面沒有帶this的自身元素。所以只需用拷貝法即可。
另外,還可以把父元素的自身元素放到子元素的prototype里面去。(原型繼承法)
function object() {
function F(){};
F.prototype = Parent;
return new F();
}
- 同時繼承自身屬性和原型屬性
這個就是結合上述方法了。
