前言
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构造函数
详情可参考关于Javascript中的new运算符,构造函数与原型链一些理解
//构造函数
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] {}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。