1. new操作符用于创建一个给定的构造函数的对象实例,举个例子:
function Person(name,age){
this.name = name;
this.age = age;
}
const person1 = new Person('Tom',20);
console.log(person1); //Person{name:"Tom",age:20}
2. new关键字进行的操作:
新生成一个对象
链接到原型
绑定this
返回新对象
3. 自己实现一个new操作符:
function create(){
let obj = new Object(); //创建一个空的对象;
let con = [].shift.call(arguments); //获得构造函数;
obj.__proto__ = con.prototype; //链接到原型,但是此时的this还没有绑定
let result = con.apply(obj,arguments); //绑定this,执行构造函数
return typeof result === 'object'?con:obj;//确保new出来的是个对象
}
function Person(name){
this,.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
create(Person,'seven')
下面针对这个实例进行一定的解释:
4. 对arguments的理解:
1)什么是arguments?
实际上是所在函数的一个内置对象,但是并不是真正的数组,可以用数组的[i]和length,但是不能用数组的方法。
2)有什么作用?
1>JS语法不支持重载,但是可用arguments对象模拟重载的效果。
2>arguments对象:函数对象内,自动创建的专门用来接收所有参数值的类数组对象。
3>arguments[i]:获得传入的参数值。
4>arguments.length:获得传入参数的个数。
注:这里注意一下什么是重载,就是函数的方法名相同,但是参数不同,在JS中,后面的函数会把前面的同名函数覆盖掉,永远调用最后一个方法。
5. call方法、shift方法、apply方法
1)JS中的call函数,apply函数,bind函数都可以改变函数的this指向,函数运行时的函数域。
2)shift方法:删除数组的第一项,并返回删除项。
3)[].shift.call(arguments):首先shift函数获得参数数组的第一项,并且通过call函数,改变原来shift函数的指向,使其指向arguments,并对数组的第一项进行复制。而后返回一个数组。至此完成了arguments类数组转化为数组的目的。
4)apply函数在本例中的应用为外部构造器Person中的属性方法被应用到了Obj中,为Obj设置属性。
6. 对于实例对象来说,都是通过new产生的,无论是function Foo(){},还是let a = {b:1}。对于创建一个对象来说,更推荐的是自变量的方式进行对象的创建(无论是性能上,还是可读性上)。因为使用new Object()的方法创建对象需要通过作用域一层一层找到Object,试用字面量的方式就没有这个问题。
function Foo(){};//function就是一个语法糖,内部等于newFunction()
let a = {b:1};//这个字面量内部也是使用了new Object()
7.对于new来说,还需要注意一下运算符优先级:
function Foo() {
return this;
}
Foo.getName = function(){
console,log('1')
}
Foo.prototype.getNme = function(){
console.log('2')
}
new Foo.getName() //1
new Foo().getName() //2
结论:new Foo()的优先级大于new Foo。第一个函数,先执行Foo.getName(),第二个函数,先执行new Foo()产生实例,通过原型链找到Foo上的getName函数。