本文不是说如何去定义一个关键字, 仅仅是讲述如何模拟实现 new 关键字所做的事情
// 代码来自于 https://wangdoc.com/javascript/oop/new.html
function _new(constructor, params) {
// 将 arguments 对象转为数组
var args = [].slice.call(arguments)
// 取出构造函数
var constructor = args.shift()
// 创建一个空对象, 继承构造函数的 prototype 属性
var context = Object.create(constructor.prototype)
// 执行构造函数
var result = constructor.apply(context, args)
// 如果返回结果是对象, 就直接返回, 否则返回 context 对象
return (typeof result === 'object' && result != null) ? result : context
}
var actor = _new(Person, '张三', 28)
new
命令的作用 , 执行构造函数,返回一个实例对象 var obj = new Object()
一、 需要让 obj.__proto__
与 Function.prototype
保持同一个引用
对象具有一个名叫 __proto__
的属性, __proto__
的值为对象
函数具有一个名为 prototype
的属性, prototype
属性的值为对象
可以看到, 使用 new
操作符返回的对象, 具有 对象.__proto__ === 函数.prototype
关于对象的比较, 用 ===
符号, 将比较对象内部的值及对象的引用是否相等,
const hero1 = {
name: 'Batman'
};
const hero2 = {
name: 'Batman'
};
hero1 === hero1; // => true
hero1 === hero2; // => false
hero1 == hero1; // => true
hero1 == hero2; // => false
Object.is(hero1, hero1); // => true
Object.is(hero1, hero2); // => false
如此可以看出, 对象.__proto__
与 函数.prototype
指向的对象是同一个
需要实现: return出来的对象与传入的函数使用同一个对象引用
二、 this 指向问题
- 不用
new
调用, 内部的this
是global
对象; - 用
new
调用, 内部的this
,是return
出来的那个对象,
var Vehicle = function (){
this.price = 1000;
};
var v = Vehicle();
v // undefined
price // 1000
这是构造函数,做的事情是向this
这个对象中添加属性;
额外提一点, 构造函数会挂载到 Vehicle.prototype.constructor
属性上, 所以有 Vehicle === Vehicle.prototype.constructor
普通函数(区别于箭头函数,箭头函数没有自己的this,也就不能做为构造函数)内部的 this
是一个对象, 由调用者传入, js中所有函数调用,最终都会转为对象的方法调用,
Vehicle()
转为 global.Vehicle()
, 所以, global
调用的 Vehicle
, Vehicle
内部的 this
是 global
对象;
总结: 需要修改内部的this指向, 从global改到 待 return 出来的对象
最后, return
出来的对象, 需要有函数中设置的属性, 如上面的 price
属性, 如果添加属性呢? 只需要调用它, 让它向this上挂载属性就行
// 第一个参数为构造函数: 内部具有this属性的非箭头函数,
function _new(constructor, ...rest) {
// 传入Object.create的对象, 最终会放到新对象的__propto__属性上
var context = Object.create(constructor.prototype);
// 执行构造函数, 让函数向this这个对象上添加属性, 并且把this从global改为需要return的对象
var result = constructor.apply(context, rest);
// new 操作符总是返回一个对象, 如果不是对象会被忽略并返回{}
return (typeof result === 'object' && result != null) ? result : context
}
function Person(name, age){
this.name = name;
this.age = age;
}
var actor = _new(Person, '张三', 28)
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!