new运算符
js中添加了new可以根据构造函数新建一个对象
function Person () {
this.name = 'mike';
this.age = 24;
}
js中任何函数都可以视为构造函数,只需要在调用函数的时候添加一个new运算符:
- 上述函数如果直接调用Person(),将直接执行,将name与age绑定在global对象上,而在浏览器环境,global一般即window,故执行后可以得到
window.name === 'mike'; // true
window.age === 24; // true
- 若添加new运算符,即new Person(),运行结果将返回一个对象,对象上绑定了name和age
const person = new Person();
person.name === 'mike'; // true
person.age === 24; // true
console.log(window.name, window.age); // undefined, undefined
new的实现
new运算符实际进行了三步操作
- 新建一个对象
- 在新建对象上新建__proto__属性,并指向构造函数的原型
- 以新建对象作为上下文上运行构造函数
- 针对构造函数的返回,如果其为对象,则返回该对象,如果其不为对象,则返回上述新建的对象
function new() {
// 新建对象
const obj = {};
// 分离出第一个参数,即传入的构造函数
const constructor = [].shift.call(arguments);
// 新建__proto__属性
obj.__proto__ = constructor.prototype;
// shift已经将构造函数分离出去了,这里的arguments只剩下构造函数入参
// 以obj作为上下文运行构造函数
const ret = constructor.apply(obj, arguments);
if (ret && typeof ret !== 'object') return ret; // null也是typeof object, 故先判空
return obj;
}
const person = new(Person);
person instanceOf Person; // true
用new运算符和执行new()的效果等同。
- 另外需要注意一下,每创建一个函数对象,系统都会给他添加一个prototype属性,指向他的原型对象,而这个原型对象上会默认得到一个constructor属性,指向他的构造函数,即指向该函数对象本身,从而完成原型链
- 又因为函数本身也是一个对象,它相当于继承自Function对象,即function Person()等价于Person = new Function(),所以函数本身也有原型链
- 而原型也是一个对象,继承自Object对象,也有原型链
- 最后,Object原型对象就是最原始的对象,他的__proto__属性为null,结合上述例子
const person = new Person();
// person和Person不直接产生联系,通过原型对象产生联系
person.__proto__ === Person.prototype; // true
Person.prototype.constructor === Person; // true
Person.prototype.__proto__ === Object.prototype; // true
Object.prototype.constructor === Object; // true
Object.prototype.__proto__ === null; // true
// Function.prototype上有各种方法通用的方法,如apply以及call
Person.__proto__ === Function.prototype; // true
Function.prototype.constructor === Function; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.constructor === Object; // true
Object.prototype.__proto__ === null; // true
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。