我决定练习js和代码调用函数。尽管如此,我还是被"undefined undefined"
输出卡住了。这是代码:
var alex = {
name: "alex",
surname: "surname",
}
let nameyourself = function() {
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling = function(smth) {
smth.__proto__.calledfunct = this;
return smth.__proto__.calledfunct();
}
nameyourself.calling(alex);
但当我删除.__proto__
时,一切都很好。我想函数没有得到alex
的上下文。
你是对的,那是因为它没有得到正确的上下文。
让我们检查一下:
当你这样做时:
nameyourself.calling(alex)
smth
得到alex
的值,即{name:"alex", surname:"surname",}
。
smth
的[[Prototype]]
(由__proto__
表示的内部属性(是Object.prototype
,因为smth
是一个普通对象。
所以这行:
smth.__proto__.calledfunct=this
基本上等于:
Object.prototype.calledfunct=this
然后,你这样称呼它(原因与上述相同(:
Object.prototype.calledfunct()
由于上下文将是在方法调用的情况下调用其属性的对象,因此使用上下文Object.prototype
调用nameyourself
。
因为Object.prototype
既没有name
属性,也没有surname
属性,所以您会得到两次undefined
。
自己测试:
var alex = {
name: "alex",
surname: "surname",
}
let nameyourself = function() {
console.log('Object.prototype === this',Object.prototype === this) //true
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling = function(smth) {
console.log('smth', smth)
console.log('smth.__proto__', smth.__proto__)
console.log('smth.__proto__ === Object.prototype', smth.__proto__ === Object.prototype) //true
smth.__proto__.calledfunct = this;
console.log('smth.__proto__.calledfunct', smth.__proto__.calledfunct)
console.log('Object.prototype.calledfunct', Object.prototype.calledfunct)
console.log('smth.__proto__.calledfunct === Object.prototype.calledfunct', smth.__proto__.calledfunct === Object.prototype.calledfunct) //true
return smth.__proto__.calledfunct();
}
nameyourself.calling(alex);
此解决方案的附带说明:
尽管这段代码可以工作(至少没有.__proto__
(,但它包含了多种不良做法。测试是可以的,但在生产中使用此代码是个坏主意。
问题:
- 定义原型方法而不使其成为非
enumerable
:改为使用Object.defineProperty
定义它们 - 扩展原生原型:将其子类化
- 在不恢复更改的情况下修补函数调用中的属性:请改用内置的
Function#call
或Function#apply
方法
这就是我修复它的方法:
var alex={
name:"alex",
surname:"surname",
}
let nameyourself = function(){
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling=function(smth){
console.log(Object.getPrototypeOf(smth));
smth.__proto__.calledfunct=this;
return smth.calledfunct();
}
nameyourself.calling(alex);