比我們通過乙個建構函式new了乙個新物件,建構函式的原型prototype指向乙個物件,所有通過該建構函式new的新物件可以共享它所包含的屬性和方法。
建構函式的原型prototype是乙個物件,那麼它也可以有自己的建構函式原型prototype,通過這樣,形成乙個原型鏈。原型鏈最終都可以上溯到object.prototype。object.prototype的__proto__是null。null沒有任何屬性和方法,也沒有自己的原型。因此,原型鏈的盡頭就是null。
來看乙個例子:
function test() {}
var test = new test();
test.__proto__===test.prototype
test.prototype.__proto__===object.protype
object.protype.__proto__===null
test.__proto__.__proto__.__proto__ === null
test.__proto__===function.prototype
獲取物件原型api: object.getprototypeof(a) 即a.proto(tip: 方法在object上而不是object.prototype上)
為了更清晰地理解,看以下練習:
var obj= {}
obj.__proto__ === object.prototype // 為 true
var fn = function(){}
fn.__proto__ === function.prototype // 為 true
fn.__proto__.__proto__ === object.prototype // 為 true
var array =
array.__proto__ === array.prototype // 為 true
array.__proto__.__proto__ === object.prototype // 為 true
array.__proto__ === function.prototype // 為 true, array的本質為乙個建構函式
實際上,看a.__proto__是什麼,就看a的本質是什麼:
1.new出來的物件,則指向其建構函式的prototype;
2.建構函式,則function.prototype
new的過程:
初始化乙個新物件
該物件的__proto__屬性指向建構函式的原型prototype
將建構函式的this指向新物件,並執行函式
將新物件返回
[如果建構函式有返回乙個物件(null除外),則將建構函式內的物件返回]
手寫new:
function mynew(func, ...params) ;
obj.__proto__ = func.prototype
if(temp && typeof temp === 'object') else
}
在這裡插播乙個經常面試的知識點:
既然知道這三個方法是用來改變this指向,那麼可以利用this在方法中誰呼叫指向誰的特性,將函式繫結到物件上,執行後再刪除
context.fn = this;
context.fn(...params)
delete context.fn
}function.prototype.mycall = function (context, ...params)
function.prototype.mybind = function (context, params)
}function person(name, age)
let obj = {}
let obj1 = {}
let obj2 = {}
person.mycall(obj1, 'lf', 18)
person.mybind(obj2, ['lf', 18])()
既然通過原型鏈例項能訪問到上層的一些方法和屬性,那麼,自然而然繼承可以由他來實現。
最容易想到的是,讓建構函式的原型指向另乙個你想要繼承的建構函式的例項,如下:
// 原型鏈繼承
// 缺點1:任何乙個例項改變原型的屬性,所有例項的原型屬性都會變,因為指向的是同乙個
// 缺點2:沒有辦法在不影響所有物件例項的情況下,給超型別的建構函式傳遞引數
function father(firstname)
function son(lastname)
son.prototype = new father('lee')
const a = new son('mei')
const b = new son('lei')
a.ver[0] = '3.0'
console.log(a)
console.log(b)
通過上面的流程也可以很好地去理解es6中的extends。
class father
update(firstname)
}class son extends father
update(firstname, lastname)
}// 通過觀察xiao的結構可以看出,原理大概是終極版
let xiao = new son('lee', 'mei')
看看下面的兩個例子:
function f1()
}f1.prototype.f2=function()
class s1 extends f1
k2()
}new s1().f1();
new s1().k1();
new s1().k2() ;
function f1()
}class s1 extends f1
}new s1().f1();
new s1().k1();
這些輸出你做對了嗎?
tips:當你呼叫super()時,解析為呼叫父類的constructor。當你呼叫super. ***(),解析為呼叫父類的原型物件上的方法。
原型 原型鏈 繼承
原型 是function物件的乙個屬性,它定義了建構函式 製造出的物件 的公共祖先。通過該建構函式產生的物件,可以繼承該原型的屬性和方法。原型也是物件 這定義有點模糊,用 解釋一下 我們在控制台中列印出了這個,首先son物件的建構函式是foo,但是我們的foo中什麼屬性都沒有,怎麼會出現乙個 pro...
原型 原型鏈 繼承
在 js 中,一切皆物件!下面就讓我們從建立物件開始,逐步學習js中的核心知識 原型,原型鏈,繼承等 1.字面量方式建立物件 var obj var obj1 2.使用 new object 的方式建立物件 var obj2 new object obj2.name 張三 obj2.age 13 o...
原型 原型鏈和繼承
看一段 就明白了function person nick,age person.prototype.sayname function var p1 newperson byron 20 var p2 newperson casper 25 p1.sayname byron p2.sayname ca...