new
1、认识new运算符
// 1、创建一个构造函数
function Animal(name) {
this.name = name;
}
Animal.color = 'red';
Animal.prototype.say() = function() {
console.log('my name is ' + this.name)
}
// 2、通过new来实例化一个对象
const cat = new Animal('cat');
cat.name; // => cat
cat.say(); // => my name is cat
有上述代码我们可以了解到,通过new运算符,我们可以根据构造函数创建一个实例,并继承这个实例的原型方法,new存在的意义在于它实现了javascript中的继承,而不仅仅是实例化了一个对象!那么new关键字具体干了什么呢?
2、new 做了如下操作
1、创建了一个空对象
2、链接到原型(空对象的`__proto__`成员指向构造对象`prototype`成员对象)
3、改变this的指向,让this指向新创建的实例对象
4、返回一个新对象
用伪代码模拟其工作流程如下:
new Animal('cat') =function() {
// 1、创建一个空对象
var obj = {};
// 2、链接到原型
obj.__proto__ = Animal.prototype;
// 3、改变this的指向,让this指向新创建的实例对象
var result = Animal.call(obj, 'cat')
// 4、返回一个新对象
return typeof result === 'object'? result : obj;
}
new 通用流程
function myNew() {
//1、创建一个空对象
const obj = {}
//2、取出参数第一个构造函数
const contructor = [].shift.call(arguments);
// 3、链接到原型
obj.__proto__ = contructor.prototype;
// 4、改变this的指向
const result = contructor.apply(obj,arguments);
// 5、返回一个新对象
return typeof result === 'object'? result : obj;
}
3、对于 new 来说,还需要注意下运算符优先级。
function Foo() {
return this;
}
Foo.getName = function () {
console.log('1');
};
Foo.prototype.getName = function () {
console.log('2');
};
new Foo.getName(); // -> 1
new Foo().getName(); // -> 2
从上图可以看出,new Foo() 的优先级大于 new Foo ,所以对于上述代码来说可以这样划分执行顺序
new (Foo.getName());
(new Foo()).getName();
对于第一个函数来说,先执行了 Foo.getName() ,所以结果为 1;对于后者来说,先执行 new Foo() 产生了一个实例,然后通过原型链找到了 Foo 上的 getName 函数,所以结果为 2。