Object.create 和 new 區別與原理

Object.create 和new 區別與原理

今天無意中看到一篇關於 Object.create 和 new 區別的博客,看完後覺得很不對勁。再一看評論,果然有問題。所以寫個通俗易懂的博客,也再次理清自己的思緒。我會先說原型鏈的一些概念,從原型鏈講他們的區別,引出繼承的例子,順便引出 new 實現的原理,最後給出完整的 Object.create 規範

(一)Object.create 和 new 區別

因爲那篇文章的作者似乎沒弄清原型鏈的一些問題,所以首先你得有這個概念,參考我以前博客

ES6 Class 的原生寫法
https://blog.csdn.net/u014168594/article/details/79448711

在這裏插入圖片描述

截取我博客中的圖:

1.Object.create 是創建一個新對象,使用現有的對象來提供新創建對象的 _proto_。意思就是生成一個新對象,該新對象的 _proto_(原型) 指向現有對象。

2.new 生成的是構造函數的一個實例,實例繼承了構造函數及其 prototype(原型屬性)上的屬性和方法。

function a(){
	this.name = 1
}
a.prototype.sayName = function(){
	console.log(1)
}
var a1 = new a()
var a2 = Object.create(a.prototype)

看上面代碼,從代碼分析更直觀

對象 a2 的 _proto_ 指向 a.prototype, 只繼承了 a 的原型方法 sayName

在這裏插入圖片描述

a1 是構造函數 a 的實例,繼承了構造函數 a 的屬性 name及其 prototype(原型) 的原型方法 sayName

在這裏插入圖片描述

兩者不同在於,Object.create 創建的新函數並沒有繼承構造函數的屬性和方法,只繼承了原型方法和原型屬性

這就是爲什麼組合寄生式繼承優於普通的組合繼承的地方,因爲之前已經繼承過一次,不再重複繼承多一次原型的屬性和方法。

組合繼承

function SuperType(name) {	
	this.name = name;	
	this.colors = ["red","green","black"];
}; 
SuperType.prototype.sayName = function() {
	return this.name
}; 
function SubType(name, age) {	
	SuperType.call(this, name);	//繼承一次
	this.age = age;
}; 

/* 普通組合繼承 */
SubType.prototype = new SuperType();	//繼承第二次

/* 組合寄生 */
function inherit(sub,super){
	var prototype = Object.create(super.prototype)	//不發生第二次繼承
	prototype.constructor =  sub
	sub.prototype = prototype 
}
inherit(SubType,SuperType)

SubType.prototype.sayAge = function () {return this.age};

(二)new 實現原理

從上面幾張圖我們已經知道了 new 其實就是在實現 Object.create (使用現有的對象來提供新創建的對象 _proto_)的基礎上,繼承了原對象的屬性和方法

function a(){
	this.name = 1
}
a.prototype.sayName = function(){
	console.log(1)
}
var a1 = new a()

這個例子實際上就幹了三件事

var a1 = {}		//創建一個空對象
a1._proto_  =  a.prototype	//使用現有的對象來提供新創建對象的  \_proto_
a.call(a1) 		//繼承原對象屬性和方法

所以我們在對象原型裏面 x.prototype 裏面增加屬性和方法會被繼承,就是因爲這個 proto 屬性

(三)Object.create() 規範

Object.create()方法創建一個新對象,使用現有的對象來提供新創建的對象的__proto__。

Object.create(proto, [propertiesObject])

proto

新創建對象的原型對象,可以爲 null。

propertiesObject

可選。如果沒有指定爲 undefined,則是要添加到新創建對象的可枚舉屬性(即其自身定義的屬性,而不是其原型鏈上的枚舉屬性)對象的屬性描述符以及相應的屬性名稱。這些屬性對應Object.defineProperties()的第二個參數

返回值

一個新對象,帶着指定的原型對象和屬性。

例子

var o = {}
o = Object.create(Object.prototype, {
	// foo會成爲所創建對象的數據屬性
	foo: { 
		writable:true,
		configurable:true,
		value: "hello" 
	},
	// bar會成爲所創建對象的訪問器屬性
	bar: {
		configurable: false,
		get: function() { return 10 },
		set: function(value) {
		  console.log("Setting `o.bar` to", value);
		}
	}
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章