Max*_*ich 1243 javascript this
我注意到,似乎没有明确解释this关键字是什么以及如何在Stack Overflow站点上的JavaScript中正确(和错误地)使用它.
我亲眼目睹了一些非常奇怪的行为,并且无法理解为什么会发生这种行为.
this工作如何以及何时使用?
Dan*_*ien 1305
我建议先阅读Mike West的文章Scope in JavaScript(mirror).它是thisJavaScript中概念和范围链的优秀,友好的介绍.
一旦你开始习惯this,规则实际上非常简单.所述的ECMAScript 5.1标准定义this:
§11.1.1的
this关键字所述
this关键字的计算结果为当前执行上下文的ThisBinding的值
ThisBinding是JavaScript解释器在评估JavaScript代码时维护的东西,比如一个特殊的CPU寄存器,它保存对象的引用.每当在三种不同情况之一中建立执行上下文时,解释器就会更新ThisBinding:
这是在顶层评估的JavaScript代码的情况,例如直接在<script>:
<script>
alert("I'm evaluated in the initial global execution context!");
setTimeout(function () {
alert("I'm NOT evaluated in the initial global execution context.");
}, 1);
</script>
Run Code Online (Sandbox Code Playgroud)
在初始全局执行上下文中评估代码时,ThisBinding设置为全局对象window(第10.4.1.1节).
...通过直接调用eval()
ThisBinding保持不变; 它与调用执行上下文的ThisBinding(§10.4.2(2)(a))的值相同.
...如果不是通过直接调用eval()
ThisBinding ,则将其设置为全局对象,就像在初始全局执行上下文中执行一样(第10.4.2(1)节).
§15.1.2.1.1定义了直接调用的eval()内容.基本上,eval(...)是直接呼叫,而类似(0, eval)(...)或var indirectEval = eval; indirectEval(...);间接呼叫eval().在JavaScript中查看chuckj对(1,eval)('this')vs eval('this')的回答?和Dmitry Soshnikov的ECMA-262-5详细介绍.第2章严格模式.适用于何时使用间接eval()呼叫.
调用函数时会发生这种情况.如果在对象上调用函数,例如in obj.myMethod()或等效函数obj["myMethod"](),则将ThisBinding设置为对象(obj在示例中; §13.2.1).在大多数其他情况下,ThisBinding设置为全局对象(第10.4.3节).
在"大多数其他情况下"编写的原因是因为有八个ECMAScript 5内置函数允许在参数列表中指定ThisBinding.这些特殊函数采用所谓thisArg的函数,在调用函数时成为ThisBinding(第10.4.3节).
这些特殊的内置功能是:
Function.prototype.apply( thisArg, argArray )Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )Array.prototype.every( callbackfn [ , thisArg ] )Array.prototype.some( callbackfn [ , thisArg ] )Array.prototype.forEach( callbackfn [ , thisArg ] )Array.prototype.map( callbackfn [ , thisArg ] )Array.prototype.filter( callbackfn [ , thisArg ] )在Function.prototype函数的情况下,它们在函数对象上调用,但不是将ThisBinding设置为函数对象,而是将ThisBinding设置为thisArg.
在Array.prototype函数的情况下,callbackfn在执行上下文中调用给定,其中ThisBinding设置为thisArgif;如果提供的话; 否则,到全局对象.
这些是纯JavaScript的规则.当您开始使用JavaScript库(例如jQuery)时,您可能会发现某些库函数会操纵它的值this.这些JavaScript库的开发人员这样做是因为它倾向于支持最常见的用例,并且库的用户通常会发现这种行为更方便.当传递引用this库函数的回调函数时,您应该参考文档以获得有关this函数调用时的值的任何保证.
如果您想知道JavaScript库如何操纵它的值this,那么库只是使用一个接受a的内置JavaScript函数thisArg.您也可以使用回调函数编写自己的函数,并且thisArg:
function doWork(callbackfn, thisArg) {
//...
if (callbackfn != null) callbackfn.call(thisArg);
}
Run Code Online (Sandbox Code Playgroud)
我还没有提到一个特例.当通过构造一个新的对象new操作时,JavaScript解释器创建一个新的空对象,设置一些内部属性,然后调用新对象的构造函数.因此,当一个函数被调用在构造方面,的值this是解释创建的新对象:
function MyType() {
this.someData = "a string";
}
var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);
Run Code Online (Sandbox Code Playgroud)
箭头功能(在ECMA6中引入)改变了范围this.请参阅现有的规范问题,箭头函数与函数声明/表达式:它们是等效/可交换的吗?欲获得更多信息.但简而言之:
箭头函数没有自己的
this....绑定.相反,这些标识符在词法范围内像任何其他变量一样被解析.这意味着在箭头函数内部,this...this指定环境中的箭头函数定义的值.
要显示答案,请将鼠标悬停在浅黄色框上.
this标记线的价值是多少?为什么?
window- 标记的行在初始全局执行上下文中进行评估.
if (true) {
// What is `this` here?
}
Run Code Online (Sandbox Code Playgroud)执行this时标记线的值obj.staticFunction()是多少?为什么?
obj- 在对象上调用函数时,ThisBinding设置为该对象.
var obj = {
someData: "a string"
};
function myFun() {
return this // What is `this` here?
}
obj.staticFunction = myFun;
console.log("this is window:", obj.staticFunction() == window);
console.log("this is obj:", obj.staticFunction() == obj);
Run Code Online (Sandbox Code Playgroud)
this标记线的价值是多少?为什么?
window在此示例中,JavaScript解释器输入功能代码,但由于未在对象上调用
myFun/obj.myMethod,因此将ThisBinding设置为window.这与Python不同,在Python中访问method(
obj.myMethod)会创建绑定方法对象.
var obj = {
myMethod: function () {
return this; // What is `this` here?
}
};
var myFun = obj.myMethod;
console.log("this is window:", myFun() == window);
console.log("this is obj:", myFun() == obj);
Run Code Online (Sandbox Code Playgroud)
this标记线的价值是多少?为什么?
window这个很棘手.在评估eval代码时,
this是obj.但是,在eval代码中,myFun不会在对象上调用,因此将ThisBinding设置window为调用.
function myFun() {
return this; // What is `this` here?
}
var obj = {
myMethod: function () {
eval("myFun()");
}
};
Run Code Online (Sandbox Code Playgroud)this标记线的价值是多少?为什么?
obj该行
myFun.call(obj);正在调用特殊的内置函数Function.prototype.call(),该函数接受thisArg作为第一个参数.
function myFun() {
return this; // What is `this` here?
}
var obj = {
someData: "a string"
};
console.log("this is window:", myFun.call(obj) == window);
console.log("this is obj:", myFun.call(obj) == obj);
Run Code Online (Sandbox Code Playgroud)
Mah*_*aha 149
this与其他语言相比,JavaScript中的关键字行为有所不同.在面向对象语言中,this关键字引用类的当前实例.在JavaScript中,值this主要由function(context.function())的调用上下文和调用它的位置决定.
1.在全球范围内使用时
this在全局上下文中使用时,它绑定到全局对象(window在浏览器中)
document.write(this); //[object Window]
Run Code Online (Sandbox Code Playgroud)
当您this在全局上下文中定义的函数内部使用时,this仍然绑定到全局对象,因为该函数实际上是一个全局上下文的方法.
function f1()
{
return this;
}
document.write(f1()); //[object Window]
Run Code Online (Sandbox Code Playgroud)
上面f1是一个全局对象的方法.因此我们也可以在window对象上调用它,如下所示:
function f()
{
return this;
}
document.write(window.f()); //[object Window]
Run Code Online (Sandbox Code Playgroud)
2.在对象内部使用时
在this对象方法中使用关键字时,this绑定到"立即"封闭对象.
var obj = {
name: "obj",
f: function () {
return this + ":" + this.name;
}
};
document.write(obj.f()); //[object Object]:obj
Run Code Online (Sandbox Code Playgroud)
我在上面用双引号括起来.它的目的是指出,如果将对象嵌套在另一个对象中,则this绑定到直接父对象.
var obj = {
name: "obj1",
nestedobj: {
name:"nestedobj",
f: function () {
return this + ":" + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
Run Code Online (Sandbox Code Playgroud)
即使您将函数显式添加到对象作为方法,它仍然遵循上述规则,this仍然指向直接父对象.
var obj1 = {
name: "obj1",
}
function returnName() {
return this + ":" + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
Run Code Online (Sandbox Code Playgroud)
3.调用无上下文函数时
当您使用this在没有任何上下文(即不在任何对象上)时调用的内部函数时,它将绑定到全局对象(window在浏览器中)(即使该函数在对象内部定义).
var context = "global";
var obj = {
context: "object",
method: function () {
function f() {
var context = "function";
return this + ":" +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
Run Code Online (Sandbox Code Playgroud)
尝试所有功能
我们也可以尝试以上功能.但是有一些差异.
this.指定它们.new运算符创建其实例.下面我尝试了我们使用Object和this上面做的所有事情,但首先创建函数而不是直接编写对象.
/*********************************************************************
1. When you add variable to the function using this keyword, it
gets added to the function prototype, thus allowing all function
instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
this.name = "ObjDefinition";
this.getName = function(){
return this+":"+this.name;
}
}
obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************
2. Members explicitly added to the function protorype also behave
as above: all function instances have their own copy of the
variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
return "v"+this.version; //see how this.version refers to the
//version variable added through
//prototype
}
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
3. Illustrating that the function variables added by both above
ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2
//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
4. `this` keyword refers to the immediate parent object. If you
nest the object through function prototype, then `this` inside
object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj',
getName1 : function(){
return this+":"+this.name;
}
};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************
5. If the method is on an object's prototype chain, `this` refers
to the object the method was called on, as if the method was on
the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
//as its prototype
obj3.a = 999; //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
//calling obj3.fun() makes
//ProtoObj.fun() to access obj3.a as
//if fun() is defined on obj3
Run Code Online (Sandbox Code Playgroud)
4.在构造函数内部使用时.
当函数用作构造函数时(即使用new关键字调用它时),this函数体内部指向正在构造的新对象.
var myname = "global context";
function SimpleFun()
{
this.myname = "simple function";
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default `new` makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
Run Code Online (Sandbox Code Playgroud)
5.在原型链中定义的函数内部使用时
如果方法在对象的原型链上,则this此类方法内部引用调用该方法的对象,就好像该方法是在对象上定义的一样.
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3's prototype but
//`this.a` inside fun() retrieves obj3.a
Run Code Online (Sandbox Code Playgroud)
6.内部调用(),apply()和bind()函数
Function.prototype.this执行函数时将使用的值.它们还会在调用时将任何参数传递给原始函数.fun.apply(obj1 [, argsArray])设置obj1为thisinside 的值fun()并调用fun()传递元素argsArray作为其参数.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 设置obj1为thisinside 的值,fun()并将调用作为参数fun()传递arg1, arg2, arg3, ....fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- 返回对函数的引用,其中fun包含this内部fun绑定obj1和fun绑定到指定参数的参数arg1, arg2, arg3,....apply,call并且bind必须变得明显.apply允许指定用作类数组对象的参数,即具有数字length属性的对象和相应的非负整数属性.而call允许直接指定函数的参数.双方apply并call立即调用函数中指定的上下文和用指定的参数.另一方面,bind只需返回绑定到指定this值和参数的函数.我们可以通过将其赋值给变量来捕获对此返回函数的引用,之后我们可以随时调用它.function add(inc1, inc2)
{
return this.a + inc1 + inc2;
}
var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
//above add.call(o,5,6) sets `this` inside
//add() to `o` and calls add() resulting:
// this.a + inc1 + inc2 =
// `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
// `o.a` i.e. 4 + 5 + 6 = 15
var g = add.bind(o, 5, 6); //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />"); //15
var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
// 4 + 5 + 6 = 15
document.write(h() + "<br />"); //NaN
//no parameter is passed to h()
//thus inc2 inside add() is `undefined`
//4 + 5 + undefined = NaN</code>
Run Code Online (Sandbox Code Playgroud)
7. this内部事件处理程序
this直接使用内部事件处理函数指的是相应的元素.这种直接功能分配可以使用addeventListener方法或通过传统的事件注册方法来完成onclick.this直接在<button onclick="...this..." >元素的事件属性(如)中使用时,它引用该元素.this通过事件处理函数或事件属性内部调用的其他函数间接使用会解析为全局对象window.attachEvent.它不是将函数赋值给事件处理程序(从而构成元素的函数方法),而是调用事件上的函数(在全局上下文中有效地调用它).我建议在JSFiddle中更好地尝试这个.
<script>
function clickedMe() {
alert(this + " : " + this.tagName + " : " + this.id);
}
document.getElementById("button1").addEventListener("click", clickedMe, false);
document.getElementById("button2").onclick = clickedMe;
document.getElementById("button5").attachEvent('onclick', clickedMe);
</script>
<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>
<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id="button5">click() "attached" using attachEvent() </button>
Run Code Online (Sandbox Code Playgroud)
use*_*110 61
this考虑以下功能:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
Run Code Online (Sandbox Code Playgroud)
请注意,我们在正常模式下运行它,即不使用严格模式.
在浏览器中运行时,其值this将记录为window.这是因为window是Web浏览器范围内的全局变量.
如果在node.js之类的环境中运行同一段代码,this则会引用应用程序中的全局变量.
现在,如果我们通过将语句添加"use strict";到函数声明的开头来以严格模式运行它,则this不再引用任何一个环境中的全局变量.这样做是为了避免严格模式中的混淆.this在这种情况下,只会记录undefined,因为它就是它,它没有被定义.
在下面的例子中,我们将看到如何操纵值this.
有不同的方法来做到这一点.如果有一个名为Javascript中就像调用本地方法forEach和slice,你应该已经知道,this在这种情况下,变量是指Object在其上被称为该函数(请注意,在JavaScript中,刚才的一切是Object,包括ArrayS和FunctionS).以下面的代码为例.
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Run Code Online (Sandbox Code Playgroud)
如果a Object包含一个包含a的属性Function,则该属性称为方法.调用此方法时,将始终将其this变量设置Object为与其关联的变量.对于严格和非严格模式都是如此.
请注意,如果某个方法存储(或者更确切地说,复制)在另一个变量中,则该引用将this不再保留在新变量中.例如:
// continuing with the previous code snippet
var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation
Run Code Online (Sandbox Code Playgroud)
考虑更常见的实际情况:
var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
Run Code Online (Sandbox Code Playgroud)
new关键字考虑Javascript中的构造函数:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
Run Code Online (Sandbox Code Playgroud)
这是如何运作的?好吧,让我们看看当我们使用new关键字时会发生什么.
new关键字调用函数会立即初始化Object类型Person.Object构造函数设置为Person.另外,请注意typeof awal只会返回Object.Object将被分配原型Person.prototype.这意味着Person原型中的任何方法或属性都可用于所有实例Person,包括awal.Person现在调用函数本身; this作为对新构造的对象的引用awal.挺直的,嗯?
请注意,官方的ECMAScript spec no no声明这类函数是实际constructor函数.它们只是普通的功能,new可以用于任何功能.只是我们这样使用它们,所以我们只将它们称为它们.
call和apply所以是的,既然functions也是Objects(实际上是Javascript中的第一类变量),甚至函数都有方法......好吧,函数是自己的.
所有函数都从全局继承,其中有Function两个方法是call和apply,并且都可以用来操作this它们被调用的函数的值.
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
这是一个典型的使用示例call.它基本上采用第一个参数并this在函数中设置foo为引用thisArg.传递给的所有其他参数call都foo作为参数传递给函数.
所以上面的代码将登录{myObj: "is cool"}, [1, 2, 3]控制台.非常好的方式来改变this任何功能的价值.
apply几乎与call接受相同,它只需要两个参数:thisArg和一个包含要传递给函数的参数的数组.所以上面的call调用可以翻译成apply这样:
foo.apply(thisArg, [1,2,3])
Run Code Online (Sandbox Code Playgroud)
请注意,call并且apply可以覆盖this我们在第二个项目符号中讨论的点方法调用设置的值.很简单:)
bind!bind是的哥call和apply.它也是FunctionJavascript中全局构造函数的所有函数继承的方法.之间的差异bind和call/ apply是,无论call和apply实际上将调用该函数.bind另一方面,使用thisArg和arguments预设返回一个新函数.让我们举个例子来更好地理解这个:
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */
bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`
Run Code Online (Sandbox Code Playgroud)
看到三者之间的区别?它很微妙,但它们的使用方式不同.喜欢call和apply,bind也this将通过点方法调用覆盖set 的值.
另请注意,这三个函数都不会对原始函数进行任何更改.call并将apply从新构造的函数返回值,同时bind返回新构造的函数本身,准备调用.
有时,您不喜欢this随范围更改的事实,特别是嵌套范围.看一下下面的例子.
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw \o/
foo.bar("args", function () {
// I want to call `hello` here
this.hello(); // error
// but `this` references to `foo` damn!
// oh wait we have a backup \o/
that.hello(); // "world"
});
}
};
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我们看到this使用嵌套范围更改的值,但我们想要this原始范围的值.因此,我们"复制" this到that和使用的副本,而不是this.聪明,是吗?
指数:
this默认保留?new关键字怎么办?this与call和apply?bind.this以解决嵌套范围问题.aru*_*ngh 48
"这个"就是范围.每个函数都有自己的作用域,因为JS中的所有东西都是一个对象,所以即使函数也可以使用"this"将一些值存储到自身中.OOP 101教导"this"仅适用于对象的实例.因此,每次执行一个函数时,该函数的新"实例"都具有"this"的新含义.
大多数人在尝试在匿名闭包函数中使用"this"时会感到困惑:
(function(value) {
this.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = this.value; // uh oh!! possibly undefined
});
})(2);
所以在这里,在每个()中,"this"不包含你期望它的"值"(来自
this.value = value;它上面).因此,为了克服这个问题(没有双关语)问题,开发人员可以:
(function(value) {
var self = this; // small change
self.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = self.value; // phew!! == 2
});
})(2);
试试看; 你会开始喜欢这种编程模式
Sep*_*eph 17
this在Javascript中始终引用正在执行的函数的"所有者" .
如果未定义显式所有者,则引用最顶层的所有者(窗口对象).
所以,如果我这样做
function someKindOfFunction() {
this.style = 'foo';
}
Run Code Online (Sandbox Code Playgroud)
element.onclick = someKindOfFunction;
this会引用元素对象.但要小心,很多人犯了这个错误
<element onclick="someKindOfFunction()">
在后一种情况下,您只需引用该函数,而不是将其移交给元素.因此,this将引用窗口对象.
car*_*rso 16
由于这个帖子已经出现了问题,我已经为新this主题的读者编写了几点.
this确定?我们使用类似于我们在英语等自然语言中使用代词的方式:"约翰跑得快,因为他试图赶上火车."相反,我们可以写"...... 约翰试图赶上火车".
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
Run Code Online (Sandbox Code Playgroud)
this 在对象调用定义它的函数之前,不会为其赋值.在全局范围中,所有全局变量和函数都在window对象上定义.因此,this在全局函数中指的是(并且具有值)全局window对象.
如果use strict,this在全球和在未绑定到任何物体匿名函数持有的价值undefined.
在以下情况下,this关键字最容易被误解:1)我们借用一个使用的方法this,2)我们分配一个用于this变量的方法,3)使用的函数this作为回调函数传递,4)this在闭包内使用 -内在的功能.(2)

在ECMA Script 6中定义,箭头函数采用this封闭(函数或全局)范围的绑定.
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Run Code Online (Sandbox Code Playgroud)
虽然箭头函数提供了使用的替代方法bind(),但重要的是要注意它们基本上禁用传统this机制,以支持更广泛理解的词法范围.(1)
参考文献:
blo*_*ead 13
javascript中的每个函数 执行上下文都有一个范围 上下文, 该参数由以下设置:
无论该范围上下文是什么,都由"this"引用.
您可以更改设置的值这个 范围 情况下使用func.call,func.apply或func.bind.
默认情况下,什么迷惑大多数初学者,当回调的事件是一个DOM元素上引发之后监听器被调用时,作用域上下文 这个函数的值是的DOM元素.
jQuery使用jQuery.proxy改变这一点.
zan*_*ngw 10
这里是一个很好的来源this在JavaScript.
以下是摘要:
全球这个
在浏览器中,在全局范围内,this是window对象
<script type="text/javascript">
console.log(this === window); // true
var foo = "bar";
console.log(this.foo); // "bar"
console.log(window.foo); // "bar"
Run Code Online (Sandbox Code Playgroud)
在node使用repl时,this是顶级命名空间.你可以称之为global.
>this
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
...
>global === this
true
Run Code Online (Sandbox Code Playgroud)
在node从脚本执行this时,全局范围作为空对象开始.它不一样global
\\test.js
console.log(this); \\ {}
console.log(this === global); \\ fasle
Run Code Online (Sandbox Code Playgroud)这个功能
除了DOM事件处理程序或thisArg提供a的情况(参见下文),在节点和浏览器中使用this未调用的函数都new引用全局范围...
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
Run Code Online (Sandbox Code Playgroud)
如果你使用use strict;,在这种情况下this将是undefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
Run Code Online (Sandbox Code Playgroud)
如果你调用一个函数new的this将是一个新的环境,也不会引用全局this.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
Run Code Online (Sandbox Code Playgroud)
您创建的函数将成为函数对象.它们会自动获取一个特殊prototype属性,您可以为其赋值.通过调用函数创建实例时,new可以访问分配给prototype属性的值.您可以使用访问这些值this.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
Run Code Online (Sandbox Code Playgroud)
分配数组或对象通常是错误的prototype.如果您希望每个实例都有自己的数组,请在函数中创建它们,而不是原型.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
Run Code Online (Sandbox Code Playgroud)
您可以this在对象的任何函数中使用它来引用该对象上的其他属性.这与使用创建的实例不同new.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
Run Code Online (Sandbox Code Playgroud)
在HTML DOM事件处理程序中,this始终是对事件附加到的DOM元素的引用
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
Run Code Online (Sandbox Code Playgroud)
除非你bind的背景
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
Run Code Online (Sandbox Code Playgroud)
您可以在其中放置JavaScript的HTML内部属性this是对元素的引用.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
Run Code Online (Sandbox Code Playgroud)
您可以使用eval访问权限this.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
Run Code Online (Sandbox Code Playgroud)
您可以使用with添加this到当前作用域来读取和写入值this而无需this显式引用.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
Run Code Online (Sandbox Code Playgroud)
jQuery在很多地方都会this引用一个DOM元素.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
Run Code Online (Sandbox Code Playgroud)
丹尼尔,很棒的解释!this在事件处理程序的情况下,这个和良好的执行上下文指针列表上的几个单词.
用两个词来说,this在JavaScript中指向运行当前函数的对象(或从其执行上下文)并且它始终是只读的对象,无论如何都无法设置它(这样的尝试最终将会出现'无效左手'一边分配'消息.
对于事件处理程序:内联事件处理程序,例如<element onclick="foo">,覆盖之前和之前附加的任何其他处理程序,所以要小心,最好不要使用内联事件委托.感谢Zara Alaverdyan,他通过不同的辩论激励我参加这个例子清单:)
el.onclick = foo; // in the foo - objel.onclick = function () {this.style.color = '#fff';} // objel.onclick = function() {doSomething();} // In the doSomething -
Windowel.addEventListener('click',foo,false) // in the foo - objel.attachEvent('onclick, function () { // this }') // window, all the
compliance to IE :)<button onclick="this.style.color = '#fff';"> // obj<button onclick="foo"> // In the foo - window, but you can <button
onclick="foo(this)">可能最详细和最全面的文章this如下:
背后的想法this是理解函数调用类型对设置this值具有重要意义.
遇到麻烦时this,不要问自己:
从何
this而来?
但不要问自己:
如何调用该函数?
对于箭头函数(上下文透明度的特殊情况),请问自己:
this箭头函数定义的值是多少?
这种心态在处理时是正确的,this并且可以帮助您避免头痛.
关于如何在JavaScript中解释"this"关键字存在很多困惑.希望这篇文章能够让所有人一劳永逸地休息.还有更多.请仔细阅读整篇文章.预先警告这篇文章很长.
无论使用它的上下文,"this"总是引用Javascript中的"当前对象".但是,"当前对象"根据上下文而不同.所述上下文可以是恰好1 6的以下内容:
以下逐一描述每个上下文:
全局背景(即所有功能之外):
在所有函数之外(即在全局上下文中),"当前对象"(以及因此"this"的值)始终是浏览器的 "窗口"对象.
内部直接"非约束函数"调用:
在直接"非绑定函数"调用内部,调用函数调用的对象变为"当前对象"(因此"this"的值).如果在没有显式当前对象的情况下调用函数,则当前对象是"窗口"对象(对于非严格模式)或未定义(对于严格模式).全局上下文中定义的任何函数(或变量) 自动成为"窗口"对象的属性.例如,假设函数在全局上下文中定义为
function UserDefinedFunction(){
alert(this)
}
Run Code Online (Sandbox Code Playgroud)
它成为窗口对象的属性,就好像您已将其定义为
window.UserDefinedFunction=function(){
alert(this)
}
Run Code Online (Sandbox Code Playgroud)
在"非严格模式"中,直接通过"UserDefinedFunction()"调用/调用此函数 将自动调用/调用它作为"window.UserDefinedFunction()"使"窗口"作为 "当前对象"(因此值"这个")在"UserDefinedFunction"中.在"非严格模式"中调用此函数将导致以下结果
UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction()
Run Code Online (Sandbox Code Playgroud)
在"严格模式"中,通过"UserDefinedFunction()"直接调用/调用该函数 将"NOT"自动调用/调用它作为"window.UserDefinedFunction()".具有"当前对象"(以及"this"的值)) "UserDefinedFunction"中的内容应该是未定义的.在"严格模式"中调用此功能将导致以下结果
UserDefinedFunction() // displays undefined
Run Code Online (Sandbox Code Playgroud)
但是,使用window对象显式调用它将导致以下结果
window.UserDefinedFunction() // "always displays [object Window] irrespective of mode."
Run Code Online (Sandbox Code Playgroud)
让我们看另一个例子.请查看以下代码
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction
}
var o2={
c:3,
d:4,
f:UserDefinedFunction
}
o1.f() // Shall display 1,2,undefined,undefined
o2.f() // Shall display undefined,undefined,3,4
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我们看到当通过o1调用"UserDefinedFunction"时,"this"取值为o1,并显示其属性"a"和"b"的值.的值"C"和"d"被示出为未定义为O1没有定义这些属性
类似地,当"UserDefinedFunction"是通过调用O2, "这"取的值O2和其属性的值"C"和"d"获得的displayed.The值的"a"和"b"的被示出为未定义为o2的确实没有定义这些属性.
内部间接"非约束函数"通过functionName.call和functionName.apply调用:
当通过functionName.call或functionName.apply调用 "非绑定函数"时,"当前对象"(以及因此"this"的值)被设置为传递给调用的"this"参数(第一个参数)的值 /申请.以下代码演示了相同的内容.
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction
}
var o2={
c:3,
d:4,
f:UserDefinedFunction
}
UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
o1.f.call(o2) // Shall display undefined,undefined,3,4
o1.f.apply(o2) // Shall display undefined,undefined,3,4
o2.f.call(o1) // Shall display 1,2,undefined,undefined
o2.f.apply(o1) // Shall display 1,2,undefined,undefined
Run Code Online (Sandbox Code Playgroud)
上面的代码清楚地表明,任何"NON Bound Function"的"this"值都可以通过call/apply来改变.此外,如果未将 "this"参数显式传递给call/apply,则"当前对象"(因此"this"的值)在非严格模式下设置为"window",在严格模式下设置为"undefined".
在"绑定函数"调用内部(即通过调用functionName.bind绑定的函数):
绑定函数是其"this"值已修复的函数.以下代码演示了绑定函数时"this"的工作原理
function UserDefinedFunction()
{
alert(this.a + "," + this.b + "," + this.c + "," + this.d)
}
var o1={
a:1,
b:2,
f:UserDefinedFunction,
bf:null
}
var o2={
c:3,
d:4,
f:UserDefinedFunction,
bf:null
}
var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
bound1() // Shall display 1,2,undefined,undefined
var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
bound2() // Shall display undefined,undefined,3,4
var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
bound3() // Shall display undefined,undefined,3,4
var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
bound4() // Shall display 1,2,undefined,undefined
o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
o1.bf() // Shall display undefined,undefined,3,4
o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
o2.bf() // Shall display 1,2,undefined,undefined
bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
Run Code Online (Sandbox Code Playgroud)
如上面的代码所示,任何"绑定函数"的"this"值都不能通过call/apply来改变.此外,如果未将"this" 参数显式传递给bind,则"当前对象" (因此"this"的值)在非严格模式下设置为"window",在严格模式下设置为"undefined".还有一件事.绑定已绑定的函数不会更改"this"的值.它仍然设置为第一个绑定函数设置的值.
通过"新"创建对象:
在构造函数内部,"当前对象"(以及"this"的值 )引用当前通过"new"创建的对象,而不管函数的绑定状态如何.但是,如果构造函数是绑定函数,则应使用为绑定函数设置的预定义参数集调用它.
内联DOM事件处理程序内部:
请查看以下HTML代码段
<button onclick='this.style.color=white'>Hello World</button>
<div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
Run Code Online (Sandbox Code Playgroud)
上述示例中的"this"分别表示"button"元素和"div"元素.
在第一个示例中,单击按钮时的字体颜色应设置为白色.
在单击"div"元素的第二个示例中,它将调用OnDivClick函数,其第二个参数引用单击的div元素.但是, OnDivClick 中"this"的值不会引用单击的div 元素.它应分别在Non strict和Strict Modes中设置为"window object"或 "undefined"(如果OnDivClick是未绑定的函数)或设置为预定义的Bound值(如果OnDivClick是绑定函数)
以下总结了整篇文章
在全局上下文中,"this"总是指"窗口"对象
无论何时调用函数,都会在对象("当前对象")的上下文中调用它.如果当前对象没有明确规定,在当前的对象 是"窗口对象"在非严格模式和"不确定"默认情况下在严格模式.
非绑定函数中"this"的值是在调用函数的上下文中对对象的引用("当前对象")
非绑定函数中"this"的值可以通过调用和应用函数的方法来覆盖 .
"this"的值对于Bound函数是固定的,并且不能通过调用和应用函数的方法来覆盖.
绑定和已绑定的函数不会更改"this"的值.它仍然设置为第一个绑定函数设置的值.
构造函数中"this"的值是正在创建和初始化的对象
内联DOM事件处理程序中"this"的值是对给定事件处理程序的元素的引用.
这是我见过的最好的解释. 了解JavaScript的这种清晰
在此引用总是指(并保持的值)的物体的单一对象,而且它通常是一个函数或方法内使用,虽然它可以在函数外,在全球范围内使用.请注意,当我们使用严格模式时,它在全局函数和未绑定到任何对象的匿名函数中保存undefined的值.
有四个条件,其中这可能会造成混淆:
他给出了我认为非常有用的代码示例,解释和代码修复.
如果你不完全理解JS,很难掌握JS,或者写出更多的东西.你不能只是快速下降:)我认为开始使用JS的最佳方式是首先观看道格拉斯·克罗克福德的这些视频讲座 - http://yuiblog.com/crockford/,它涵盖了这一点和那个,以及关于JS的一切.
小智 6
在伪古典术语中,许多讲座教授'this'关键字的方式是作为由类或对象构造函数实例化的对象.每次从一个类构造一个新对象时,想象一下,创建并返回一个'this'对象的本地实例.我记得它是这样教的:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
Run Code Online (Sandbox Code Playgroud)
this是JavaScript中一个被误解的概念之一,因为它的行为因地而异。简单来说,this是指我们当前正在执行的函数的“所有者”。
this帮助获取我们正在使用的当前对象(又名执行上下文)。如果你了解这是越来越当前执行的函数对象,你可以很容易地了解当前thisIS
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Run Code Online (Sandbox Code Playgroud)
在上方,我们创建了3个具有相同名称“ val”的变量。一个在全局上下文中,一个在obj内部,另一个在obj的innerMethod内部。JavaScript通过将范围链从本地扩展到全局来解析特定上下文中的标识符。
很少this可以区分的地方
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Run Code Online (Sandbox Code Playgroud)
当执行line1时,JavaScript将为函数调用建立执行上下文(EC),设置this为最后一个“”之前的内容所引用的对象。。因此,在最后一行中,您可以了解它a()是在全局上下文中执行的window。
this 可用于引用正在创建的对象
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Run Code Online (Sandbox Code Playgroud)
Person()执行new时,将创建一个全新的对象。Person被调用,它this被设置为引用该新对象。
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Run Code Online (Sandbox Code Playgroud)
如果我们错过了new关键字,则whatIsThis指向它可以找到的最全局的上下文(window)
如果事件处理程序为内联,则this引用全局对象
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
Run Code Online (Sandbox Code Playgroud)
通过JavaScript添加事件处理程序时,this是指生成事件的DOM元素。
.apply() .call()和操作上下文.bind()var that = thisJavaScript代表什么小智 5
“ this”的值取决于在其中执行功能的“上下文”。上下文可以是任何对象或全局对象,即窗口。
因此,“ this”的语义不同于传统的OOP语言。这会导致问题:1.将函数传递给另一个变量(最有可能是回调)时;2.从类的成员方法调用闭包时。
在两种情况下,都将其设置为window。
| 归档时间: |
|
| 查看次数: |
390124 次 |
| 最近记录: |