js中的上下文问题



我决定练习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#callFunction#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);

最新更新