- 作者:老汪软件技巧
- 发表时间:2024-12-15 17:04
- 浏览量:
引言
在JS 中,new操作符是一个非常重要的特性,它允许我们创建对象并调用构造函数来初始化这些对象。在面试中,手写new是一个非常常见的考点。本文将深入探讨new操作符的工作原理,并通过手写实现一个类似new操作符功能的函数。
new操作符的作用
在JS中,使用new操作符可以创建一个新的对象,并将这个对象的原型链链接到构造函数的原型对象上。同时,它还会执行构造函数,并将构造函数中的this 绑定到新创建的对象上。这样,我们就可以通过构造函数来初始化新创建的对象的属性和方法。
例如,以下是使用new操作符创建一个Person对象的示例,来帮助我们理解new到底都干了些什么事:
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayName=function(){
console.log(this.name);
}
// new 实例化运算符
// 1. 创建一个空对象 {} 和 Person 没有血缘关系
// {} __proto__ Object.prototype
// 2. 手动的__proto__ 指向 Person.prototype
// 3. 构造函数 this 指向 {} 执行,给{}赋值
const zzz=new Person('zzz',20);
在这个例子中,我们定义了一个构造函数Person,它接受两个参数name和age,并在构造函数内部将这两个参数赋值给新创建的对象的属性。同时,我们还在Person的原型对象上定义了一个方法sayName ,这个方法可以打印出对象的name属性。最后,我们使用new操作符创建了一个Person对象,并调用了它的sayName方法。
new操作符的工作原理
了解了new操作符的作用后,我们来深入探讨一下它的工作原理。当我们使用new操作符时,JS引擎会执行以下几个步骤:
创建一个空对象 {}将这个新对象的原型链链接到构造函数的原型对象上执行构造函数,并将构造函数中的this 绑定到新创建的对象上如果构造函数返回一个非原始值(即对象或函数),则返回这个值。否则,返回新创建的对象手写new
下面我们来手写一个new:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function () {
console.log(this.name);
}
// 不设置形参 使用arguments 获取参数
function objectFactory() {
// arguments 所有参数 类数组
// console.log(arguments,arguments.length);
const obj = new Object(); // 1. 空对象创建
// arguments 类数组 没有shift 方法 借给 arguments shift方法
// [].shift.call(arguments) 将类数组 转为数组 使用 shift
const Constructor = [].shift.call(arguments)
// console.log(Constructor);
// 2. 手动的__proto__ 指向 Person.prototype
obj.__proto__ = Constructor.prototype;
// 3. this 指向 apply 第二项是数组
const result = Constructor.apply(obj,arguments);
// console.log(obj);
// 4. 如果构造函数返回的是一个对象,则返回这个对象;否则返回新创建的对象
return result instanceof Object ? result : obj;
}
// 传参为函数名和各项值
let awei = objectFactory(Person,'zzz',20)
console.log(zzz.name); // zzz
zzz.sayName(); // zzz
在这个实现中,我们首先创建了一个空对象obj,然后将这个对象的原型链链接到构造函数的原型对象上。接着,我们使用apply方法执行构造函数,并将构造函数中的this绑定到新创建的对象上。最后,返回对象obj。
步骤分析
在上面的方法中使用到的一些方法,我会在下面做一下解释:
arguments:这是一个伪数组(类数组对象), 它包含了传递给函数的所有参数。arguments 只能在函数体内访问[].shift.call(arguments):shift()定义在Array.prototype上,只能由数组使用。arguments是伪数组,没有shift()方法。我们通过一个空数组[ ]来调用shift(),并使用call()绑定到arguments上来让伪数组使用shift()方法。将函数名赋给Constructorobj.__proto__ = Constructor.prototype:将这个新对象的原型链链接到构造函数的原型对象上,保证实现new的功能Constructor.apply(obj,arguments):使用apply确定函数Constructor的this指向创建的新对象obj,将剩下的arguments作为参数一起传给函数Constructor。这里绑定this使用的是apply,apply可以将所有参数用数组的方式一起传送,call只能一个一个传值。最后,如果构造函数返回的是一个对象,则返回这个对象;否则返回新创建的对象
至此,一个简单的手写new就完成了!!!
总结
通过深入解析new操作符的机制并手写实现一个简易版本。手写new作为面试中一道常考题,希望这篇文章能够帮助到你。