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 |
var A = function(){ |
解釋:首先 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 |
function Person(name){ |
call() 和 apply() 的區別:call() 的參數是扁平化參數,apply() 的第二參數放在數組中
例:
1 |
Math.max.apply(,) |
4. 實現繼承的套路:
1 |
function Person(name){ |