new关键字和创建对象的几种方式

343 阅读3分钟

相关内容

  • 创建对象的几种方式?
  • 三者的区别是什么?
  • new 的内部发生了什么?
  • Object.create 的应用?

创建对象的方式

有几种创建对象的方式,字面量相对于 new 创建对象有哪些优势?

创建对象的几种方式:

  • 字面量
  • new 构造函数
  • Object.create()

字面量

对于字面量创建对象:

var obj= {
  name: "jack"
}

字面量创建对象的优势所在:

  • 代码量更少,更易读;
  • 对象字面量运行速度更快,它们可以在解析的时候被优化。他不会像 new 一个对象一样,解析器需要顺着作用域链从当前作用域开始查找,如果在当前作用域找到了名为 Object() 的函数就执行,如果没找到,就继续顺着作用域链往上照,直到找到全局 Object() 构造函数为止;

new 构造函数

对于 new 创建对象

let arr = new Object();

new 的过程包含以下四个阶段:

  • 创建一个新对象
  • 这个新对象的 __proto__ 属性指向原函数的 prototype 属性
  • 将这个新对象绑定到此函数的 this
  • 返回新对象
function myNew(Con, ...args) {
  // 创建空对象,设置空对象的原型(链接对象的原型)
  let obj = Object.create(Con.prototype);
  // 绑定 this 并执行构造函数(为对象设置属性)
  let result = Con.apply(obj, args);
  // 返回 obj 对象
  return typeof result === "object" ? result : obj;
}

// 构造函数
function Test(name, age) {
  this.name = name;
  this.age = age;
}

Test.prototype.sayName = function () {
  console.log(this.name);
};

const f1 = myNew(Test, "jack", 25);
console.log(f1); // Test {name: "jack", age: 25}
f1.sayName(); // jack

Object.create()

对于 Object.create() 方式创建对象:

Object.create(proto, [propertiesObject]);
  • proto:新创建对象的原型对象。
  • propertiesObject:(可选)可为创建的新对象设置属性和值。
    • configurable
      • true 当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除;
      • 默认为 false
    • enumerable
      • true 当且仅当在枚举相应对象上的属性时该属性显现;
      • 默认为 false
    • value
      • 与属性关联的值。可以是任何有效的 JavaScript 值(数字,对象,函数等);
      • 默认为 undefined
    • writable
      • true 当且仅当与该属性相关联的值可以用assignment operator改变时;
      • 默认为 false
    • get
      • 作为该属性的 getter 函数,如果没有 getter 则为 undefined。函数返回值将被用作属性的值;
      • 默认为 undefined
    • set
      • 作为该属性的 setter 函数,如果没有 setter 则为 undefined。函数将仅接受参数赋值给该属性的新值 ;
      • 默认为 undefined

应用场景:一般用于继承

var People = function (name){
  this.name = name;
};

People.prototype.sayName = function (){
  console.log(this.name);
}

function Person(name, age){
  this.age = age;
  People.call(this, name); // 使用call,实现了People属性的继承
};

// 使用Object.create()方法,实现People原型方法的继承,并且修改了constructor指向
Person.prototype = Object.create(People.prototype, {
  constructor: {
    configurable: true,
    enumerable: true,
    value: Person,
    writable: true
  }
});

Person.prototype.sayAge = function (){
  console.log(this.age);
}

var p1 = new Person('person1', 25);

p1.sayName();  // 'person1'
p1.sayAge();   // 25

三者创建对象的区别

  • new 和 字面量创建的对象的原型指向 Object.prototype,会继承 Object 的属性和方法;
  • 而通过 Object.create(null) 创建的对象,其原型指向 nullnull 作为原型链的顶端,没有也不会继承任何属性和方法;