你好,我是南一。这是我在准备面试八股文的笔记,如果有发现错误或者可完善的地方,还请指正,万分感谢🌹
模拟实现new
这里我采用函数,来模拟new运算符
MDN对new操作符的描述
new 关键字会进行如下的操作:
- 创建一个空的简单 JavaScript 对象(即
{}); - 为步骤 1 新创建的对象添加属性
__proto__,将该属性链接至构造函数的原型对象 ; - 将步骤 1 新创建的对象作为
this的上下文 ; - 如果该函数没有返回对象,则返回
this。
据此可以写出第一版New函数
function Father(name, age) {
this.name = name;
this.age = age;
// return {
// a: 'a'
// }
}
function New(...rest) {
//创建一个新的对象
const obj = {};
//获取构造函数
const ConstructedFunction = rest.shift();
//这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性。
obj.__proto__ = ConstructedFunction.prototype;
//让构造函数的 this 指向这个新的对象, 并拿到执行结果
const result = ConstructedFunction.apply(obj, rest);
//返回新对象, 如果构造函数返回一个对象,那new就返回这个对象,否则返回新建的对象
return result instanceof Object ? result : obj;
}
console.log(New(Father, 'baba', 45));
console.log(new Father('baba', 45));
提出问题
如果第一个参数不是构造函数怎么办呢?
抛出错误处理!!!
//如果第一个参数不是构造函数 就抛出错误
if (!(ConstructedFunction instanceof Function)) {
//抛出错误ConstructedFunction不是一个构造函数
return new TypeError(`${ConstructedFunction + ''} is not a constructor`)
}
ES5有个APIObject.create()
用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)
new改进版
function Father(name, age) {
this.name = name;
this.age = age;
}
function New(...rest) {
//获取第一个参数 构造函数
const ConstructedFunction = rest.shift();
//如果第一个参数不是构造函数 就抛出错误
if (!(ConstructedFunction instanceof Function)) {
//抛出错误ConstructedFunction不是一个构造函数
return new TypeError(`${ConstructedFunction + ''} is not a constructor`)
}
//创建一个新的对象 Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。
//这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性。
const obj = Object.create(ConstructedFunction.prototype);
//让构造函数的 this 指向这个新的对象, 并拿到执行结果
const result = ConstructedFunction.apply(obj, rest);
//返回新对象, 如果构造函数返回一个对象,那new就返回这个对象,否则返回新建的对象
return result instanceof Object ? result : obj;
}
console.log(New(Father, 'baba', 45)); // Father { name: 'baba', age: 45 }
如果面试官不给用ES6扩展符...
利用arguments对象获取参数,ES6不给用,那const也都改成var
function Father(name, age) {
this.name = name;
this.age = age;
}
function New() {
//用Array.prototype.slice.call(arguments),将arguments对象转数组
var rest = Array.prototype.slice.call(arguments)
//获取第一个参数 构造函数
var ConstructedFunction = rest.shift();
//如果第一个参数不是构造函数 就抛出错误
if (!(ConstructedFunction instanceof Function)) {
//抛出错误ConstructedFunction不是一个构造函数
return new TypeError(`${ConstructedFunction + ''} is not a constructor`)
}
//创建一个新的对象 Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。
//这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性。
var obj = Object.create(ConstructedFunction.prototype);
//让构造函数的 this 指向这个新的对象, 并拿到执行结果
var result = ConstructedFunction.apply(obj, rest);
//返回新对象, 如果构造函数返回一个对象,那new就返回这个对象,否则返回新建的对象
return result instanceof Object ? result : obj;
}
console.log(New(Father, 'baba', 45)); // Father { name: 'baba', age: 45 }