淺析js中的Object.create()

咱們能夠從最初的混合繼承模式,慢慢提及Object.create()的來龍去脈。瀏覽器

1.混合模式實現原型式繼承

通常來講,使用構造函數結合原型的混合模式,能夠爲特定的實例共享屬性和方法。bash

比較常見的是下面的形式,也是最基本的使用:函數

function Person(name){
	this.name = name;
};

Person.prototype.sayName = function(){
	alert(this.name);
}

Person.prototype.XXX = XXXXX;

......

var p1 = new Person('mike');
var p2 = XXXXX;
......
複製代碼

若是隻是想達到實例共享屬性,不想噼裏啪啦的建立構造函數,懶得定義一大堆原型屬性,,徹底能夠用更簡潔的方法去實現。ui

好比,這麼作:this

定義於一個create函數,來對傳入的obj對象加工,使obj對象做爲構造函數Person的原型,最後返回一個臨時的新實例。spa

function create(obj){
	function Person(){};
	Person.prototype = obj;
	return new Person();
}

var people = {
	name:'mike'
}

var p1 = create(people);

console.log(p1.name);		//mike
複製代碼

故事還在繼續。。。prototype

上面方法證實是可行的,不過有一個坑,那就是原型的引用類型屬性會共享相應的值,舉個栗子:指針

function create(obj){
	function Person(){};
	Person.prototype = obj;
	return new Person();
}

var people = {
	name:'mike',
	arr:[1,2,3,4,5]
}

var p1 = create(people);
var p2 = create(people);

p1.name = 'jake';
p1.arr.push('hahaha');

console.log(p1.name);		//jake
console.log(p2.name);		//mike

console.log(p1.arr);		//[1, 2, 3, 4, 5, "hahaha"]
console.log(p2.arr);		//[1, 2, 3, 4, 5, "hahaha"]
複製代碼

因爲原型中的arr屬性是引用類型,因此它是被實例所共享,上面能夠看到原型中,基本類型屬性和引用類型屬性的差別。code

2.Object.create()實現原型式繼承

ES5新增了一個Object.create()方法,用於規範原型式繼承。對象

Object.create(prototype, descriptors)
複製代碼
  • prototype:必需。 要用做原型的對象。 能夠爲 null。
  • descriptors:可選。 包含一個或多個屬性描述符的 JavaScript 對象。 「數據屬性」是可獲取且可設置值的屬性。 數據屬性描述符包含 value 特性,以及 writable、enumerable 和 configurable 特性。 若是未指定最後三個特性,則它們默認爲 false。【這很重要,意味着若是不顯式聲明屬性的enumerable=true,它在某些方法下是不可枚舉遍歷的】

在只傳入一個參數的狀況下Object.create()與上面的create()用法相同:

var person = {
name:'mike',
	arr:[1,2,3,4,5]
}

var p1 = Object.create(person);
var p2 = Object.create(person);

p1.name = 'jake';
p1.arr.push('hahaha');

console.log(p1.name)		//jake
console.log(p2.name)		//mike

console.log(p1.arr)			//[1, 2, 3, 4, 5, "hahaha"]
console.log(p2.arr)			//[1, 2, 3, 4, 5, "hahaha"]
複製代碼

注意了,仍是那個坑,包含引用類型的屬性始終會共享相應的值。

Object.create()接收的第二個參數,是爲新對象定義額外的屬性,指定的任何屬性都會覆蓋原型上的同名屬性。

var person = {
	name:'mike',
	arr:[1,2,3,4,5]
}

var p1 = Object.create(person,{
	name:{
		value:'jake'
	},
	arr:{
		value:[7,8,9]
	}
});
var p2 = Object.create(person);

p1.arr.push('hahaha');

console.log(p1.name)		//jake
console.log(p2.name)		//mike

console.log(p1.arr)			//[7, 8, 9, "hahaha"]
console.log(p2.arr)			//[1, 2, 3, 4, 5]
複製代碼

如下補充於2018-09-12。

**Object.create()**還能夠用於完整克隆一個對象,包括它的原型屬性。

Object.create(
	Object.getPrototypeOf( obj ),
	Object.getOwnPropertyDescriptors( obj )
)
複製代碼

3.proto

改變對象的原型鏈指針__proto__也能夠實現繼承另外一個對象。

不推薦使用這個屬性,__proto__ 屬性只有瀏覽器必須部署,在非瀏覽器的環境不必定部署。

function Person(){
	this.sex = 'man';
}

Person.prototype.name = 'hello';

var p = new Person();

var obj = {
	addr:'china',
	__proto__:new Person
}

console.log(obj.name)	//hello

console.log(obj.sex)	//man
複製代碼

4.Object.setPrototypeOf()

ES6新增API,Object.setPrototypeOf()

Object.setPrototypeOf 方法的做用與 __proto__ 相同,用來設置一個對象的 prototype 對象,返回參數對象自己。

Object.setPrototypeOf(object, prototype)
複製代碼
function Person(){
	this.sex = 'man';
}

Person.prototype.name = 'hello';

var p = new Person();

var obj = {
	addr:'china'
}

Object.setPrototypeOf( obj, new Person )

console.log(obj.name)	//hello

console.log(obj.sex)	//man
複製代碼
相關文章
相關標籤/搜索