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 作为上下文运行构造函数
constructor.apply(obj, arguments);
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