淺談js中Object.create()與new的具體實(shí)現(xiàn)與區(qū)別
Object.create與new區(qū)別
function A() { this.name = 'abc'; } A.prototype.a = 'a'; A.prototype.showName = function () { return this.name; } var a1 = new A(); var a2 = Object.create(A.prototype);
從這個(gè)例子可以看出,a2只繼承了A原型的屬性和方法,
a1 是構(gòu)造函數(shù) A 的實(shí)例,繼承了構(gòu)造函數(shù) A 的屬性 name及其原型屬性和方法。
所以O(shè)bject.create()與new的區(qū)別在于Object.create只繼承原型屬性和方法,繼承不了構(gòu)造函數(shù)的屬性和方法。而通過(guò)new操作符創(chuàng)建的實(shí)例,既可以繼承原型的屬性和方法,又可以繼承構(gòu)造函數(shù)的屬性和方法。
Object.create()原理
Object.create = function (o) { var F = function () {}; F.prototype = o; return new F(); };
new原理
- 創(chuàng)建一個(gè)空對(duì)象obj;
- 將該空對(duì)象的原型設(shè)置為構(gòu)造函數(shù)的原型,即obj.proto = func.prototype;
- 以該對(duì)象為上下文執(zhí)行構(gòu)造函數(shù),即func.call(obj);
- 返回該對(duì)象,即return obj。
var newFunc = function ( func ){ var obj = Object.creat(func.prototype); var ret = func.call(obj); if(typeof ret === 'object') { return ret; } else { return obj; } }
從兩者的具體實(shí)現(xiàn)可以看出:Object.create沒(méi)有執(zhí)行步驟三,所以繼承不了構(gòu)造函數(shù)的屬性和方法。
繼承
a1.__proto__ == a2.__proto__; // true a1.__proto__ == A.prototype; // true a2.__proto__ == A.prototype; // true a1.__proto__.__proto__ == Object.prototype; // true a1.__proto__.__proto__.__proto__ == null; // true
比較組合繼承與寄生組合繼承
組合繼承
在子類(lèi)構(gòu)造函數(shù)中調(diào)用父類(lèi)構(gòu)造函數(shù),并把父類(lèi)實(shí)例化對(duì)象賦給子類(lèi)原型。
function Parent(name, age) { this.name = name; this.age = age; } Parent.prototype.showName = function () { return this.name; } function Child(name, age) { Parent.call(this, name, age); // 這里調(diào)用一次父類(lèi)構(gòu)造函數(shù) } Child.prototype = new Parent(); // 這里也會(huì)調(diào)用父類(lèi)構(gòu)造函數(shù) Child.prototype.constructor = Child;
這種方式在構(gòu)造函數(shù)繼承時(shí)執(zhí)行了一遍父類(lèi)構(gòu)造函數(shù),又在實(shí)現(xiàn)子類(lèi)原型繼承時(shí)調(diào)用了一遍父類(lèi)的構(gòu)造函數(shù)。因此父類(lèi)構(gòu)造函數(shù)調(diào)用了兩遍,所以這不是最優(yōu)化的繼承方式。
寄生組合繼承
function Parent(name, age) { this.name = name; this.age = age; } Parent.prototype.showName = function () { return this.name; } function Child(name, age) { Parent.call(this, name, age); // 這里調(diào)用一次父類(lèi)構(gòu)造函數(shù) } Child.prototype = Object.create(Parent.prototype); // 這里避免了調(diào)用父類(lèi)構(gòu)造函數(shù) Child.prototype.constructor = Child;
到此這篇關(guān)于淺談js中Object.create()與new的具體實(shí)現(xiàn)與區(qū)別的文章就介紹到這了,更多相關(guān)Object.create()與new區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
原生js實(shí)現(xiàn)簡(jiǎn)單滑動(dòng)解鎖功能?js實(shí)現(xiàn)滑動(dòng)拼圖解鎖
這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)簡(jiǎn)單滑動(dòng)解鎖功能,js實(shí)現(xiàn)滑動(dòng)拼圖解鎖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02js動(dòng)態(tài)添加帶圓圈序號(hào)列表的實(shí)例代碼
這篇文章主要介紹了js動(dòng)態(tài)添加帶圓圈序號(hào)列表的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02微信小程序?qū)崿F(xiàn)自定義picker選擇器彈窗內(nèi)容
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)自定義picker選擇器彈窗內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07bootstrap選項(xiàng)卡擴(kuò)展功能詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap選項(xiàng)卡擴(kuò)展功能,增加關(guān)閉,超出一行顯示下拉,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06JS基礎(chǔ)之undefined與null的區(qū)別分析
在JavaScript開(kāi)發(fā)中,被人問(wèn)到:null與undefined到底有啥區(qū)別?一時(shí)間不好回答,特別是undefined,因?yàn)檫@涉及到undefined的實(shí)現(xiàn)原理。2011-08-08