为什么在通过引用传递后调用函数时对象内部 "this" 不同?
Why is "this" different inside object when function is called after being passed by reference?
简而言之:为什么直接调用的函数和通过引用传递的函数在Javascript时有不同的"this"上下文使用对象?
In long: 我定义了一个对象,和一堆方法作为 prototypes,其中使用关键字“this" 访问对象属性。我实例化了该对象,我能够调用这些方法,一切都按预期进行。问题是这些方法中的任何一个都可能抛出一个异常,我想单独捕获每个异常。为了避免重复代码,我实现了一个 runCatch 函数,我将引用传递给要执行的方法和一个回调,当发生错误。在 runCatch 中,我基本上是在执行引用的方法,并用 try-catch[=71= 包装它],但是像这样,“this”关键字指向“Window”对象而不是 对象 本身。因此,根据我对 Javascript 上下文的了解,如果我使用 new 关键字初始化对象,则“this”上下文原型函数应该始终引用对象本身。
这是一个正在发生的事情的小例子:
https://jsbin.com/gugohubori/edit?html,js,output
HTML:
<div>Object Value (Direct Call):
<span id="val1"></span>
<div>Object Value (Passed by Reference):
<span id="val2"></span>
Javascript:
// The Object
function myobject(){
this.value = "IT WORKS"
}
myobject.prototype.getValue = function(){
return this.value;
}
var obj = new myobject(); // Instantiate Object
// Direct Call (this is correct)
document.getElementById('val1').innerText = obj.getValue();
// Call by reference funciton
function callbyref(callback){ return callback(); }
// Call by reference (this is correct)
document.getElementById('val2').innerText = callbyref(obj.getValue);
而前面代码的结果是:
对象值(直接调用):有效
对象值(通过引用传递):未定义
谁能解释一下为什么“this”的上下文因调用位置而异?让示例中的 callbyref 函数具有正确的“this 的正确方法是什么? " 指向对象的引用?
编辑: 混淆从何而来?所以对我来说主要的困惑似乎是,当你创建一个常规对象“{}”时,该对象内部的 this 的上下文是它被执行的上下文。但是,当您使用 new 关键字创建对象时,该对象内部方法的上下文将绑定到对象本身,无论它们在什么上下文中被调用。但是无论出于何种原因,当函数作为变量传递并在其他地方调用时,有界上下文会丢失(@Carloluis 对此进行了很好的解释)。
关于重复的编辑:谁能澄清为什么这个问题被标记为重复? 我知道 this Javascript 中的变量混淆广为流行,似乎是一个微妙的问题,但我在这里提出问题之前一直在研究。 post 被 link 编辑为重复问题并不能解决我的问题,而是以通用方式解释“this”变量和上下文,但从未解释过为什么使用 new 实例化的对象在作为引用传递时最终会丢失其对象上下文。我认为 @Carloluis 的回答比 link 对另一个标记为重复的不相关问题的回答更清楚。
上下文。
//Creates new instance
var obj = new myobject();
//Calls the method in the instance's context
//When a function is called as a method of an object, this is the object
obj.getValue();
//Grabs the reference to the method
var callback=obj.getValue;
//Calls the referenced method in current context, which is window
callback();
你可以试试,添加一个新的方法returns或者打印this
到控制台。
如果您需要this
始终是对象,您应该使用callback.call(obj,param)
或apply(obj,params)
。
问题是 JavaScript 中的 this
关键字值由调用函数的方式决定。
A function's this keyword behaves a little differently in JavaScript compared to other languages.
在 MDN 上阅读更多内容。
你可以认为函数调用中的 this
指向 "dot" 之前的对象,如果调用中没有任何 .
它将指向到 windows 对象(当您将 obj.getValue
的引用传递给 callbyref
函数时就是这种情况。
function MyObject(){
this.value = "IT WORKS"
}
MyObject.prototype.getValue = function(){
return this.value;
}
const myObject = new MyObject();
console.log(myObject.getValue()); // this -> { value: 'IT WORKS' }
const getValueRef = myObject.getValue;
console.log(getValueRef()); // this -> Windows object
// -- Using the `.bind` function to attach the this context
// In the new function this is permanently bound to the first argument of bind, regardless of how the function is being used.
const getValueRefBound = myObject.getValue.bind(myObject);
console.log(getValueRefBound()); // this -> myObject
在前面的代码片段中添加了一个示例,以展示如何将 this
上下文绑定到以后的函数执行,而不管它是如何使用的。
Function.prototype.bind()
The bind() method creates a new function that, when called, has its this
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
你也可以检查这个post Understanding Scope and Context in JavaScript.
简而言之:为什么直接调用的函数和通过引用传递的函数在Javascript时有不同的"this"上下文使用对象?
In long: 我定义了一个对象,和一堆方法作为 prototypes,其中使用关键字“this" 访问对象属性。我实例化了该对象,我能够调用这些方法,一切都按预期进行。问题是这些方法中的任何一个都可能抛出一个异常,我想单独捕获每个异常。为了避免重复代码,我实现了一个 runCatch 函数,我将引用传递给要执行的方法和一个回调,当发生错误。在 runCatch 中,我基本上是在执行引用的方法,并用 try-catch[=71= 包装它],但是像这样,“this”关键字指向“Window”对象而不是 对象 本身。因此,根据我对 Javascript 上下文的了解,如果我使用 new 关键字初始化对象,则“this”上下文原型函数应该始终引用对象本身。
这是一个正在发生的事情的小例子:
https://jsbin.com/gugohubori/edit?html,js,output
HTML:
<div>Object Value (Direct Call):
<span id="val1"></span>
<div>Object Value (Passed by Reference):
<span id="val2"></span>
Javascript:
// The Object
function myobject(){
this.value = "IT WORKS"
}
myobject.prototype.getValue = function(){
return this.value;
}
var obj = new myobject(); // Instantiate Object
// Direct Call (this is correct)
document.getElementById('val1').innerText = obj.getValue();
// Call by reference funciton
function callbyref(callback){ return callback(); }
// Call by reference (this is correct)
document.getElementById('val2').innerText = callbyref(obj.getValue);
而前面代码的结果是:
对象值(直接调用):有效
对象值(通过引用传递):未定义
谁能解释一下为什么“this”的上下文因调用位置而异?让示例中的 callbyref 函数具有正确的“this 的正确方法是什么? " 指向对象的引用?
编辑: 混淆从何而来?所以对我来说主要的困惑似乎是,当你创建一个常规对象“{}”时,该对象内部的 this 的上下文是它被执行的上下文。但是,当您使用 new 关键字创建对象时,该对象内部方法的上下文将绑定到对象本身,无论它们在什么上下文中被调用。但是无论出于何种原因,当函数作为变量传递并在其他地方调用时,有界上下文会丢失(@Carloluis 对此进行了很好的解释)。
关于重复的编辑:谁能澄清为什么这个问题被标记为重复? 我知道 this Javascript 中的变量混淆广为流行,似乎是一个微妙的问题,但我在这里提出问题之前一直在研究。 post 被 link 编辑为重复问题并不能解决我的问题,而是以通用方式解释“this”变量和上下文,但从未解释过为什么使用 new 实例化的对象在作为引用传递时最终会丢失其对象上下文。我认为 @Carloluis 的回答比 link 对另一个标记为重复的不相关问题的回答更清楚。
上下文。
//Creates new instance
var obj = new myobject();
//Calls the method in the instance's context
//When a function is called as a method of an object, this is the object
obj.getValue();
//Grabs the reference to the method
var callback=obj.getValue;
//Calls the referenced method in current context, which is window
callback();
你可以试试,添加一个新的方法returns或者打印this
到控制台。
如果您需要this
始终是对象,您应该使用callback.call(obj,param)
或apply(obj,params)
。
问题是 JavaScript 中的 this
关键字值由调用函数的方式决定。
A function's this keyword behaves a little differently in JavaScript compared to other languages.
在 MDN 上阅读更多内容。
你可以认为函数调用中的 this
指向 "dot" 之前的对象,如果调用中没有任何 .
它将指向到 windows 对象(当您将 obj.getValue
的引用传递给 callbyref
函数时就是这种情况。
function MyObject(){
this.value = "IT WORKS"
}
MyObject.prototype.getValue = function(){
return this.value;
}
const myObject = new MyObject();
console.log(myObject.getValue()); // this -> { value: 'IT WORKS' }
const getValueRef = myObject.getValue;
console.log(getValueRef()); // this -> Windows object
// -- Using the `.bind` function to attach the this context
// In the new function this is permanently bound to the first argument of bind, regardless of how the function is being used.
const getValueRefBound = myObject.getValue.bind(myObject);
console.log(getValueRefBound()); // this -> myObject
在前面的代码片段中添加了一个示例,以展示如何将 this
上下文绑定到以后的函数执行,而不管它是如何使用的。
Function.prototype.bind()
The bind() method creates a new function that, when called, has its
this
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
你也可以检查这个post Understanding Scope and Context in JavaScript.