浅析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
复制代码
相关文章
相关标签/搜索