原型和原型鏈以及call和apply
阿新 • • 發佈:2020-12-13
一、原型
1. prototype
原型是 function
物件的一個屬性,它定義了建構函式製造出的物件的公共祖先。通過該建構函式產生的物件,可以繼承該原型的屬性和方法。原型也是物件。
可能大家對這個定義不太理解,下面我們來舉一個例子:
//Person.prototype --原型
//該原型在建構函式建立的時候就被定義好了,為一個屬性,是祖先
//Person.prototype = {}
Person.prototype.name = "alex";
function Person(){}
let p = new Person()
console.log(p.name) //輸出alex
上面程式碼中我建立了一個建構函式,但是裡面我並沒有傳值,按理說什麼都不會輸出,但是像原型的定義說的,prototype是構造出的物件的祖先,該物件會繼承該原型的屬性和方法。
prototype
這個屬性是一個指標,指向一個物件,而這個物件的用途是包含可以有特定型別的所有例項共享的屬性和方法。prototype
是通過呼叫建構函式而建立的那個物件例項的原型物件。
2. _ proto _
物件具有屬性__proto__
,可稱為隱式原型,一個物件的隱式原型指向構造該物件的建構函式的原型,這也保證了例項能夠訪問在建構函式原型中定義的屬性和方法。
Person.prototype.name = "alex";
function Person(){}
let p = new Person()
console.log(p)
console.log(p.__proto__)
輸出結果
構造出來的p物件指向Person
,然後裡面有個__proto__
屬性,而 name
和 constructor
等屬性都在__proto__
屬性中。
接下來我們再看一個例子:
function Foo(){}
var Boo = {name: "Boo"};
Foo.prototype = Boo;
var f = new Foo();
console.log(f.__proto__ === Foo.prototype); // true
console.log(f.__proto__ === Boo); // true
Object.getPrototypeOf(f) === f.__proto__; // true
3. prototype 和 __ proto __ 的區別
__proto__
是每個物件都有的一個屬性,而prototype
是函式才會有的屬性
使用
Object.getPrototypeOf()
可以代替__proto__
4. 原型鏈
5. call() 和 apply()
每個函式都包含兩個非繼承而來的方法:apply()
和 call()
call
與 apply
都屬於Function.prototype
的一個方法,所以每個function
例項都有call
、apply
屬性
① 作用:改變this
的指向
② 區別:接收引數的方式不同
- call():第一個引數是
this
值沒有變化,變化的是其餘引數都直接傳遞給函式。在使用call()
方法時,傳遞給函式的引數必須逐個列舉出來。 - apply():傳遞給函式的是引數陣列
function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34