前言
PS:2018/04/14: 重新梳理一下发现以前说的有问题,顺便比较两两写法之间的差异性.
1、使用“对象字面量”表示法
console.time('函数字面量运行时间');
//嵌套函数字面量
var Person = {
name: 'one'
};
Person.getName = function () {
console.log(this.name);
}
//调用方法
Person.getName(); // one
console.timeEnd('函数字面量运行时间') // 函数字面量运行时间: 4.969ms
2、使用new操作符后跟Object构造函数
//构造函数
function Person(name) {
this.name = name
}
//原型添加方法
Person.prototype.getName = function () {
console.log(this.name);
}
console.time('构造函数运行时间');
//生成实例
var Person = new Person('two');
//调用方法
Person.getName(); // two
console.timeEnd('构造函数运行时间'); // 构造函数运行时间: 5.435ms
当代码执行时会经过几个步骤:
1,一个继承自Person.prototype的新对象被创建.
2,创建执行的时候,同时上下文(this)会被指定为这个新实例
3,执行构造函数中的代码(设置新对象的__proto__属性指向构造函数的prototype对象等)
4,new出来的结果为步骤1创建的对象
3、使用Object.create(prototype, descriptors)
这是E5中提出的一种新的对象创建方式,对主流浏览器友好,创建一个具有指定原型且可选择性地包含指定属性的对象。(详情可参考Object.create 函数 (JavaScript))
参数
描述
prototype(必需)
要用作原型的对象,可以为 null
descriptors(可选)
包含一个或多个属性描述符的 JavaScript 对象
返回值
一个具有指定的内部原型且包含指定的属性(如果有)的新对象;
异常
prototype 参数不是对象且不为 null;
descriptors 参数中的描述符具有 value 或 writable 特性,并具有 get 或 set 特性;
descriptors 参数中的描述符具有不为函数的 get 或 set 特性;
需要注意descriptors“数据属性”是可获取且可设置值的属性.数据属性描述符包含 value 特性,以及 writable、enumerable 和 configurable 特性.如果未指定最后三个特性,则它们默认为 false.只要检索或设置该值,“访问器属性”就会调用用户提供的函数. 访问器属性描述符包含 set 特性和/或 get 特性.即
//构造函数
function Person(name) {
this.name = 'name'
}
//原型添加方法
Person.prototype.getName = function () {
console.log(this.name);
}
console.time('Object.create运行时间')
//生成实例
var Person = Object.create(Person.prototype, {
name: {
value: 'three'
}
});
Person.getName(); // three
console.timeEnd('Object.create运行时间') // Object.create运行时间: 3.272ms
允许修改需要设置writable属性
//构造函数
function Person(name) {
this.name = 'name'
}
//原型添加方法
Person.prototype.getName = function () {
console.log(this.name);
}
//生成实例
var Person = Object.create(Person.prototype, {
name: {
value: 'three',
writable: true,
}
});
Person.name = 'four';
Person.getName(); // four
new和Object.create区别
function Person(name) {
this.name = 1
}
Person.prototype.name = 2;
//生成实例
var Person_new = new Person();
var Person_create = Object.create(Person);
var Person_create_prototype = Object.create(Person.prototype);
console.log(Person_new, Person_create, Person_create_prototype);
// Person { name: 1 } Function {} Person {}
区别
属性
new构造函数
Object.create(构造函数)
Object.create(构造函数原型)
实例类型
实例对象
函数
实例对象
实例name
1
无
无
原型name
2
无
2
小结
对比
new
Object.create
使用目标
函数
函数和对象
返回实例
实例对象
函数和实例对象
实例属性
继承构造函数属性
不继承构造函数属性
原型链指向
构造函数原型
构造函数/对象本身
对象字面量和Object.create区别
//构造函数
function Person(name) {
this.name = 1
}
Person.prototype.name = 2;
//生成实例
var Person1 = {
name: 1
};
var Person_create_prototype = Object.create(Person.prototype);
console.log(Person1, Person_create_prototype);
// { name: 1 } Person {}
区别
属性
对象字面量
Object.create
实例类型
纯对象
实例对象
实例name
1
无
原型name
无
2
原型链指向
Object
Person
小结
对比
对象字面量
Object.create
使用目标
纯对象
函数和对象
返回实例
纯对象
函数和实例对象
实例属性
非继承属性
不继承构造函数属性
原型链指向
Object
构造函数/对象本身
个人总结:
对象字面量是最简洁的写法;
Object.create()可以实现一个继承目标且可高度配置的对象;
Object.create(null)可以得到无继承的最纯净对象;
console.log(Object.create(null)) // [Object: null prototype] {}