JavaScript實現繼承方式

1. new

Student.prototype = new Person();
得到一個 Person 實例,並且這個實例指向構造器的 prototype 屬性和調用了構造函數,因爲調用的構造函數,而 Student 只是一個類,並沒有實例化,只爲了繼承,調用構造函數創建一個實例,參數的問題就不容易解決。

例如:當 Person() 中有一個 name 屬性時,而 Student 上也有 name 屬性時,當
Student.prototype = new Person(); Person 上的 name:undefined ,並且 Student 永遠不會用到 Person 上的 name 性,如果 Person 上有很多這樣的屬性情況可想而知。

new 操作符所做的事情(var a = new A())
a.首先生成一個空對象 a = {} ,它是 Object 的實例
b.設置 a 的原型鏈 a.proto = A.prototype
c.A.call(a), A 的 this 指向 a,並執行 A 的函數體
d.判斷 A 的返回值類型,
如果 ‘沒有返回值’ 或者 ‘返回值類型爲值類型’ 返回 this 即 a (this === a),
如果有返回值,並且返回值類型爲引用類型,就返回這個引用類型的對象,替換掉 a

1
2
3
4
5
var A = function(){
return this.__proto__;
}
var a = new A();
console.log(a) //object{}

解釋:首先 this === a, 但是 A 返回的是 this.proto (a.proto), this.proto 指向了原型對象 Object() 構造函數創建的 object 對象,它是一個引用類型,它替換掉 a ,所以這裏的變量 a 是一個指針,指向它的原型。

console.log(A.prototype === a); //true

此時 A 構造函數的原型和 a 指針(指向 a.proto)是同一個對象

2. Object.create()

var obj = Object.create({ x:1 });

Object.create()是系統內置函數,參數爲對象,返回新創建的對象,並且該對象的原型指向參數

創建空對象,並且對象的 proto 指向參數,既繼承了屬性和方法,本身又有自己的空對象,對於自己添加的屬性和方法不會去更改原型上的屬性和方法。

3. call() 和 apply()

call() 和 apply() 是爲了動態改變 this 而出現的,當一個 Object 沒有某個方法時,
但是其他 Object 有,可以藉助 call() 和 apply() 用其他對象的方法來操作。

call() 和 apply() 就是更改 this 指向
例:

1
2
3
4
5
6
7
8
function Person(name){
this.name = name;
}
function Student(name,Klass){
Person.call(this,name);
//此時的 Person 的 this 指向了 Student(即 call 裏面的 this)
this.klass = klass;
}

call() 和 apply() 的區別:call() 的參數是扁平化參數,apply() 的第二參數放在數組中

例:

1
2
3
4
5
6
7
Math.max.apply(,)
Math.max(1,2,3); // 3
Math.max([1,2,3]); // NaN
Math.apply(null,[1,2,3]); // 3
Math.max.apply(null,[1,2,3]) === Math.max(1,2,3); // true
Math.max.call(null,1,2,3); // 3
Math.max.call(null,1,2,3) === Math.max(1,2,3); // true

4. 實現繼承的套路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Person(name){
this.name = name;
}

Person.prototype.sayHi = fucntion(){
console.log('hi!I am '+this.name);
}

function Student(name,Klass){
Person.call(this,name); // 使用 call 繼承屬性
this.klass = klass; // 設置自身的屬性
}

// 使用 Object.create() 繼承方法
Student.prototype = Object.create(Person.prototype,{
constructor:{
value:Student;
// 還可以指定 writable configurable enumerable
}
});

// 設置自身方法
Student.prototype.learn = function(subject){
console.log(this.name + 'can learn' + subject);
}



© CZBBhkrx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章