实例对象与new命令
1. 构造函数是什么,有什么作用
- 类似于Java的Class,是对象模板;专门用来生成实例对象的函数。
- JavaScript 语言的对象体系,不是基于“类”的,而是基于构造函数(constructor)和原型链(prototype)。
- 一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。
2. new命令的作用
- 执行构造函数,返回一个实例对象。
3. 不使用new造成的影响与避免方法
- 造成的影响
- 构造函数就变成了普通函数,并不会生成实例对象。
- this这时代表全局对象。
- 避免方法
- 一个解决办法是,构造函数内部使用严格模式,即第一行加上use strict。这样的话,一旦忘了使用new命令,直接调用构造函数就会报错;由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错(JavaScript 不允许对undefined添加属性)。
function Fubar(foo, bar){ 'use strict'; this._foo = foo; this._bar = bar; } Fubar() // TypeError: Cannot set property '_foo' of undefined
2. 另一个解决办法,构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象。
function Fubar(foo, bar) { if (!(this instanceof Fubar)) { return new Fubar(foo, bar); } this._foo = foo; this._bar = bar; } Fubar(1, 2)._foo // 1 (new Fubar(1, 2))._foo // 1
4. new命令的原理
- 因为new命令总是返回一个对象,要么是this指向的实例对象,要么是return语句指定的对象。
- this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。
5. new命令代码实现
- 使用new命令时,它后面的函数依次执行下面的步骤:
- 创建一个空对象,作为将要返回的对象实例。
- 将这个空对象的原型,指向构造函数的prototype属性。
- 将这个空对象赋值给函数内部的this关键字(函数内部this指向空对象)。
- 开始执行构造函数内部的代码。
- 代码实现:
function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ params) { // 将 arguments 对象转为数组 var args = [].slice.call(arguments); // 取出构造函数 var constructor = args.shift(); // 创建一个空对象,继承构造函数的 prototype 属性 var context = Object.create(constructor.prototype); // 执行构造函数 var result = constructor.apply(context, args); // 如果返回结果是对象,就直接返回,否则返回 context 对象 return (typeof result === 'object' && result != null) ? result : context; } // 实例 var actor = _new(Person, '张三', 28);
6. 判断函数调用时是否使用new命令
- 函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined。
7. Object.create()创建实例对象
- 以这个现有的对象作为模板,生成新的实例对象