1

前言

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 特性,以及 writableenumerableconfigurable 特性.如果未指定最后三个特性,则它们默认为 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 构造函数/对象本身

个人总结:

  1. 对象字面量是最简洁的写法;
  2. Object.create()可以实现一个继承目标且可高度配置的对象;
  3. Object.create(null)可以得到无继承的最纯净对象;
console.log(Object.create(null)) // [Object: null prototype] {}

Afterward
621 声望62 粉丝

努力去做,对的坚持,静待结果