day114-实现new运算符(2)

前言

new 模拟实现大致思路:

  1. 建立一个新对象
  2. 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上
  3. 实例可以访问原型上的属性

原型的知识复习

[[prototype]] 是什么?
JavaScript中的对象,都有一个特殊的[[prototype]]内置属性,其实就是对于其他对象的引用。(你不知道的JavaScript-上卷-第五章)

__proto__ 是什么?
__proto__ ,绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)。
new.target 是什么?
new.target属性允许你检测函数或构造方法是否是通过new运算符被调用的。在通过new运算符被初始化的函数或构造方法中,new.target返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是undefined。

原型关系图:

实现代码

function myObjectFactory () {
var Constructor = [].shift.call(arguments) // 取外部传入的构造器
var newObj = Object.create(Constructor.prototype)
// newObj也可以这么写
/**
* var obj = new Object()
* obj.__proto__ = Constructor.prototype
*/
var ctorResult = Constructor.apply(newObj, arguments)
// 判断返回的值是不是一个对象,如果是一个对象,则返回对象
// 注意:判ctorResult是否空
return typeof ctorResult === 'object' ? ctorResult||newObj : newObj
}

另外一种实现

unction New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);

引自:实现一个new操作符

测试


// 测试用例-1
function Test (name) {
this.name = name
this.habit = 'Games'
}

Test.prototype.age = 22

Test.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}

var person = myObjectFactory(Test, 'zhangsan')

console.log(person.name) // zhangsan
console.log(person.habit) // Games
console.log(person.age) // 22

person.sayYourName() // I am zhangsan

// 测试用例-2 虚实__proto__(Object.create(null))
function Otaku (age) {}

Otaku.prototype.sayHello = function() {
console.log('hello')
}

var person = myObjectFactory(Otaku, 'Kevin', '18');
console.log(person) // Otaku {}
person.sayHello() // hello

参考

JavaScript深入之new的模拟实现
js中_proto_和prototype的区别和关系?
怎么实现new
new​.target

文章作者: lmislm
文章链接: http://lmislm.com/2019/05/06/2019-05-06/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LMISLMのBlog