22答案
技术说明 这
在规范中
[AO]ResolveThisBinding[…]确定关键字的绑定
这 使用的词汇环境 运行执行上下文 .[步骤]:
让 环境记录 是 获取此环境 (). 返回? 环境记录 .GetThisBinding()。
1.脚本中的全局执行上下文
<脚本> //全球背景 console.log(this);// 记录全局对象。 setTimeout(函数(){ console.log(“非全局上下文”); }); </script>
全局环境记录的GetThisBinding具体方法 环境记录 […][这样做]:
返回 环境记录 .[[GlobalThisValue]]。
2.中的全局执行上下文 模块
模块Environment Record[…][的GetThisBinding具体方法是这样做的:
返回 未定义 .
3.进入 评估 代码
A直接 评估 呼叫通常看起来像 评估( … ); 或 (评估)( … ); (或 ((评估)( … ); 等等)。 1 它只是 直接的 如果调用表达式符合窄模式。 2 间接的 评估 调用涉及调用函数引用 评估 以任何其他方式。 可能是这样 评估?。 ( … ) , ( … ,评估)( … ) , 窗口.eval( … ) , 评估呼叫( … , … ) 等给出 常量别名Eval1=eval; window.aliasEval2=评估; ,也是 别名评估1( … ) , 别名Eval2( … ) .单独给出 const originalEval=评估; window.eval=(x)=>原始评估值(x); ,正在呼叫 评估( … ) 也会是间接的。
在直接评估中 这 值不变; 它取自调用的词法范围 评估 . 在间接评估中 这 值是全局对象( 全球This ).
4.进入 功能 代码
A类 功能环境记录 是一个声明性环境记录,用于表示函数的顶级范围,如果函数不是 箭头函数 ,提供了
这 结合。 如果函数不是 箭头函数 功能和参考
超级的 ,其功能环境记录还包含用于执行的状态
超级的 方法调用。
这是
这 用于此函数调用的值。
原始参考, 函数的类型,以及 代码是否在 严格模式 .
函数环境记录的GetThisBinding具体方法 环境记录 […][这样做]:
[…] 3.退货 环境记录 .[[ThisValue]]。
箭头函数
让 this模式 是 F类 .[[此模式]]。 如果 this模式 是 词汇的 ,返回NormalCompletion(
未定义 ). […]
函数环境记录的HasThisBinding具体方法 环境记录 […][这样做]:
如果 环境记录 .[ThisBindingStatus]]为 词汇的 ,返回 假 ; 否则,返回 真的 .
箭头函数没有自己的
这 […]绑定。 相反,[这个标识符]像其他变量一样在词法范围内解析。 这意味着在一个箭头函数中,
这 [指]的[值
这 ]在环境中,箭头功能是 定义 in(即箭头功能的“外部”)。
功能 属性
常量refObj={ func:函数(){ console.log(this); } };
常量refObj={ func(){ console.log(this); } };
参考对象函数() refObj[“函数”]() 参考对象?。 func() 参考对象函数?。 () 参考对象.func``
它们都是表达, 他们都是推荐人,而且 它们都是价值观。
常数o={ a: 1、, b: this.a,//是`globalThis.a`。 [this.a]:2//表示`globalThis.a`。 };
没有基本引用、严格模式和 具有
func();// 与`refObj.func();`相反。
常数g=(f)=>f();// 无基准参考。 常数h=refObj.func; 常量j=()=>参考对象.func; g(参考对象函数); h();// 无基准参考。 j()();// 无基准参考。 (0,引用对象函数)();// 另一个常见的模式是删除基础引用。
让 this模式 是 F类 .[[此模式]]。
[…]
如果 this模式 是 严格的 ,让 this值 是 this参数 . 否则,
如果 this参数 是 未定义 或 无效的 ,然后
让 全球环境 是 被称为Realm .[[GlobalEnv]]。 […] 让 this值 是 全球环境 .[[GlobalThisValue]]。 否则,
让 this值 成为! ToObject(目标对象) (thisArgument)。 注: ToObject(目标对象) 生成包装器对象[…]。
[…]
让 参考环境 是 裁判 .[[基础]]。 断言: 参考环境 是环境记录。 让 this值 是 参考环境 .WithBaseObject()。
函数f1(){ console.log(this); } 函数f2(){ console.log(this); } 函数f3(){ console.log(this); } 常数o={ f1, f2, [符号.不透明度]:{ f2:真 } }; f1();// 记录`globalThis`。 带有(o){ f1();// 日志`o`。 f2();//` f2 `是不可传播的,所以这会记录`globalThis`。 f3();//` f3`不在`o`上,因此记录`globalThis`。 }
“使用严格”; 函数f(){ console.log(this); } f();// 日志“未定义”。 //严格模式代码中不允许使用`with`语句。
.调用
, .应用
, .绑定
, 这个Arg 、和原语
Function.prototype.apply(thisArg,argArray) 功能.原型。 { 呼叫 , 绑定 } (thisArg,…args)
函数f(){ console.log(this); } 常量myObj={}, g=f.bind(myObj), h=(m)=>m(); //所有这些日志`myObj`。 g(); f.绑定(myObj)(); f.call(myObj); h(g);
函数f(){ console.log(this); } const myString=“s”, g=f.bind(myString); g();// 日志`String{“s”}`。 f.call(myString);// 日志`String{“s”}`。
“使用严格”; 函数f(){ console.log(this); } const myString=“s”, g=f.bind(myString); g();// 日志“s”。 f.call(myString);// 日志“s”。
$(“按钮”).点击(函数(){ console.log(this);// 记录单击的按钮。 });
施工人员, 类 、和 新的
函数旧(a){ 这.p=a; } const o=新旧(1); 控制台.log(o);// 日志`Old{p:1}`。 类新建{ 建造师(a){ 这.p=a; } } const n=新建(1); 控制台.log(n);// 日志`New{p:1}`。
A级{ m1(){ 返回此; } m2(){ 常数m1=this.m1; 控制台.log(m1()); } } 新A().m2();// 日志“未定义”。
超级的
类DerivedNew扩展了New{ 构造函数(a,a2){ //在“super”之前使用“this”会导致ReferenceError。 super(a); this.p2=a2; } } const n2=新派生新(1,2); 控制台.log(n2);// 日志`DerivedNew{p:1,p2:2}`。
5.评估类字段
如果字段是静态的,那么 这 指的是类本身, 如果字段不是静态的,那么 这 引用实例。
课堂演示{ a=这个; b(){ 返回此; } 静态c=此; 静态d(){ 返回此; } //Getter、setter、private修饰符也是可能的。 } const演示=新演示; console.log(demo.a,demo.b());// 两个日志都是“demo”。 console.log(Demo.c,Demo.d());// 两个日志都是“演示”。
为了好玩,用一些例子来测试你的理解力
-
if(真){ console.log(this);// 这是什么? } 全球This 。标记行在初始全局执行上下文中求值。 常量对象={}; 函数myFun(){ return{//这里的`this`是什么? “是对象”:此===对象, “是全局this”:this===globalThis }; } obj.method=myFun; console.log(obj.method()); 对象 。将函数作为对象的属性调用时,使用 这 绑定集到 基础 参考文献的 对象方法 ,即。 对象 . 常量对象={ myMethod:function(){ return{//这里的`this`是什么? “是对象”:此===对象, “是全局this”:this===globalThis }; } }, myFun=obj.myMethod; console.log(myFun()); 全球This .由于函数值 我的乐趣 / 对象.my方法 作为属性 这 绑定将是 全球This . 这与Python不同,后者访问方法( 对象.my方法 )创建一个 绑定方法对象 . 常量对象={ myFun:()=>({//这是什么? “是对象”:此===对象, “是全局this”:this===globalThis }) }; console.log(obj.myFun()); 全球This .箭头函数不创建自己的 这 结合。 词法范围与初始全局范围相同,因此 这 是 全球This . -
函数myFun(){ console.log(this);// 这是什么? } 常量对象={ myMethod:function(){ eval(“myFun()”); } }; 对象myMethod(); 全球This 。在评估直接评估电话时, 这 是 对象 然而,在eval代码中, 我的乐趣 没有从对象中调用,因此 这 绑定设置为全局对象。 函数myFun(){ //这是什么? 返回{ “是对象”:此===对象, “是全局this”:this===globalThis }; } 常量对象={}; console.log(myFun.call(obj)); 对象 .线路 myFun.call(obj); 正在调用特殊的内置函数 功能.原型.call ,接受 这个Arg 作为第一个参数。 类别MyCls{ arrow=()=>({//这是什么? “是MyCls”:这===MyCls, “is globalThis”:this===全局this, “is instance”:MyCls的这个实例 }); } console.log(新MyCls().arrow()); 这是一个 MyCls公司 .箭头函数不会更改 这 绑定,所以它来自词汇范围。 因此,这是 完全一样 与上面提到的类字段一样,比如 a=这个; 。尝试将其更改为 静态箭头 你得到你期望的结果了吗?
-
2 -
三 @LRDPRDX好吧,这个答案包含了 这 但没有人真正需要 这 在全球范围内, 具有 已弃用, 评估 不鼓励,应在任何地方使用严格模式等。剩下的就是 对象方法() 电话 方法 具有 对象 作为 这 如果 方法 是一个 功能 或方法; func() 电话 函数 没有任何 这 ; .绑定 , .调用 、和 .应用 可用于绑定 这 明确地; 箭头函数没有得到 这 结合。 类:在静态事物中, 这 指类本身,在非状态事物中指正在创建的实例。 就是这样。 – 塞巴斯蒂安·西蒙 评论 2022年2月8日21:51
文档.写入(this)// [对象窗口]
函数f1() { 返回此; } document.write(f1())// [对象窗口]
函数f() { 返回此; } document.write(window.f())// [对象窗口]
var对象={ 名称:“obj”, f: 函数(){ return this+“:”+this.name; } }; document.write(obj.f())// [object对象]:obj
var对象={ 名称:“obj1”, 爱沙尼亚:{ 名称:“nestedobj”, f: 函数(){ return this+“:”+this.name; } } } document.write(obj.nestedobj.f())// [对象对象]:nestedobj
变量obj1={ 名称:“obj1”, } 函数returnName(){ return this+“:”+this.name; } obj1.f=返回名称// 将方法添加到对象 document.write(obj1.f())// [对象对象]:obj1
var context=“global”; 变量对象={ 上下文:“对象”, 方法:函数(){ 函数f(){ var context=“function”; return this+“:”+this.context; }; 返回f()// 在没有上下文的情况下调用 } }; document.write(obj.method())// [object Window]:全局
上面我们使用对象文字符号向对象添加了成员。 我们可以使用向函数添加成员 这 .以指定它们。 对象文字符号创建了一个可以立即使用的对象实例。 对于函数,我们可能需要首先使用 新的 操作员。 同样在对象文字方法中,我们可以使用点运算符显式地向已经定义的对象添加成员。 这只会添加到特定的实例中。 然而,我在函数原型中添加了变量,这样它就可以反映在函数的所有实例中。
/********************************************************************* 1.使用此关键字向函数添加变量时 添加到函数原型中,从而允许所有函数 实例添加自己的变量副本。 *********************************************************************/ 函数functionDef() { this.name=“对象定义”; this.getName=函数(){ 返回this+“:”+this.name; } } obj1=新函数Def(); document.write(obj1.getName()+“<br/>”)// [对象对象]:对象定义 /********************************************************************* 2.显式添加到函数protorype的成员也有行为 如上所述:所有函数实例都有自己的 添加了变量。 *********************************************************************/ functionDef.prototype.version=1; functionDef.prototype.getVersion=函数(){ return“v”+this.version// 查看this.version如何引用 //通过添加的版本变量 //原型 } document.write(obj1.getVersion()+“<br/>”)// 第1版 /********************************************************************* 3.说明上述二者添加的函数变量 方法在函数实例之间有自己的副本 *********************************************************************/ functionDef.prototype.incrementVersion=函数(){ this.version=this.version+1; } var obj2=新函数Def(); document.write(obj2.getVersion()+“<br/>”)// 第1版 obj2.incrementVersion()// obj2中的递增版本 //不影响obj1版本 document.write(obj2.getVersion()+“<br/>”)// 第2版 document.write(obj1.getVersion()+“<br/>”)// 第1版 /********************************************************************* 4.“this”关键字指的是直接父对象。 如果你 通过函数原型嵌套对象,然后在其中嵌入this 对象是指嵌套对象,而不是函数实例 *********************************************************************/ functionDef.prototype.nestedObj={名称:'nestedObj', getName1:function(){ 返回this+“:”+this.name; } }; document.write(obj2.nestedObj.getName1()+“<br/>”)// [对象对象]:嵌套对象 /********************************************************************* 5.如果方法位于对象的原型链上,则“this”表示 调用该方法的对象,就像该方法处于打开状态 对象。 *********************************************************************/ var ProtoObj={fun:function(){return this.a}}; var obj3=对象创建(ProtoObj)// 创建对象设置ProtoObj //作为其原型 obj3.a=999// 向obj3添加实例成员 document.write(obj3.fun()+“<br/>”)// 999 //调用obj3.fun()使 //ProtoObj.fun()以访问obj3.a //如果在obj3上定义了fun()
var myname=“全局上下文”; 函数SimpleFun() { this.myname=“简单函数”; } var obj1=新建SimpleFun()// 将myname添加到obj1 //1. ` new`使SimpleFun()中的`this`指向 //对象,从而添加任何成员 //使用this.membername在SimipleFun()中创建 //正在构建的对象 //2. 默认情况下,“new”使函数新返回 //构造对象(如果未指定显式返回值) document.write(obj1.myname)// 简单函数
var协议对象={ 乐趣:函数(){ 返回this.a; } }; //Object.create()创建以ProtoObj为其对象 //原型并将其分配给obj3,从而使fun() //作为其原型链上的方法 var obj3=对象创建(ProtoObj); obj3.a=999; document.write(obj3.fun())// 999 //注意,fun()是在obj3的原型上定义的,但是 //`this.a`inside-fun()检索obj3.a
所有这些方法都定义于 功能.原型 . 这些方法允许编写一次函数并在不同的上下文中调用它。 换句话说,它们允许指定 这 它将在执行函数时使用。 它们还接受在调用原始函数时传递给它的任何参数。 fun.apply(obj1[,argsArray]) 集合 对象1 作为的值 这 里面 函数() 和电话 fun() 传递元素 参数数组 作为其论据。 fun.call(对象1[,参数1[,变量2[,参数3[,…]]]) -集合 对象1 作为的值 这 里面 fun() 和电话 fun() 经过 arg1、arg2、arg3。。。 作为其论据。 fun.bind(obj1[,arg1[,arg2[,arg3[,…]]]) -返回对函数的引用 乐趣 具有 这 内部乐趣绑定到 对象1 和的参数 乐趣 绑定到指定的参数 arg1、arg2、arg3,。。。 . 到目前为止 应用 , 呼叫 和 绑定 一定很明显。 应用 允许将参数指定为类似数组的对象,即带有数字的对象 长度 属性和相应的非负整数属性。 鉴于 呼叫 允许直接指定函数的参数。 两者都有 应用 和 呼叫 在指定的上下文中使用指定的参数立即调用函数。 另一方面, 绑定 只返回绑定到指定 这 值和参数。 我们可以通过将此返回函数赋值给变量来捕获它的引用,然后可以随时调用它。
函数加法(inc1,inc2) { 返回this.a+inc1+inc2; } 变量o={a:4}; document.write(添加.call(o,5,6)+“<br/>”)// 15 //上面的add.call(o,5,6)在内部设置了“this” //将()添加到`o`并调用add(),结果是: //这个.a+inc1+inc2= //`o.a`即4+5+6=15 文档.写入(添加.应用(o,[5,6])+“<br/>”)// 15 //`o.a`即4+5+6=15 var g=添加绑定(o,5,6)// g: `o.a`即4+5+6 document.write(g()+“<br/>”)// 15 var h=添加绑定(o,5)// h: `o.a`即4+5+? 文档.写入(h(6)+“<br/>”)// 15 // 4 + 5 + 6 = 15 document.write(h()+“<br/>”)// NaN公司 //没有参数传递给h() //因此add()中的inc2是“未定义的”` //4+5+未定义=NaN
将函数直接分配给元素的事件处理程序时,使用 这 直接在事件处理函数内部引用相应的元素。 这样的直接功能分配可以使用 addeventListener(添加侦听器) 方法或通过传统的事件注册方法,如 onclick(单击) . 类似地,当您使用 这 直接在event属性内(如 <button onclick=“…这…”> )在元素中,它指的是元素。 然而,使用 这 通过事件处理函数或事件属性内调用的其他函数间接解析为全局对象 窗口 . 当我们使用Microsoft的事件注册模型方法将函数附加到事件处理程序时,也可以实现上述相同的行为 附件事件 。它没有将函数分配给事件处理程序(从而生成元素的函数方法),而是对事件调用函数(有效地在全局上下文中调用它)。
<脚本> 函数单击Me(){ 警报(this+“:”+this.tagName+“:“+this.id); } document.getElementById(“button1”).addEventListener(“click”,clickedMe,false); document.getElementById(“button2”).onclick=单击我; document.getElementById(“button5”).attachEvent(“单击”,单击我); </script> <h3>在事件处理程序或事件属性中“直接”使用`this`</h3> <button id=“button1”>使用addEventListner()单击“assigned”() <button id=“button2”>使用click()单击“分配” <button id=“button3”onclick=“alert(this+':'+this.tagName+':'+this.id);”>直接在单击事件属性中使用了`this` <h3>在事件处理程序或事件属性中“间接”使用`this`</h3> <button onclick=“alert((function(){return this+':'+this.tagName+':'+this.id;})());”>`此`在函数内部间接使用<br/>定义并调用了内部事件属性</button> <button id=“button4”onclick=“clickedMe()”>`这`是间接使用的,内部函数调用了内部事件属性 仅限IE:<button id=“button5”>使用attachEvent()单击()“attached”
(function(){}).bind(this)
const globalArrowFunction=()=>{ 返回此; }; console.log(globalArrowFunction())// 窗口 常量上下文对象={ 方法1:()=>{return this}, 方法2:函数(){ return()=>{returnthis}; } }; console.log(contextObject.method1())// 窗口 const contextLessFunction=contextObject.method1; console.log(contextLessFunction())// 窗口 console.log(contextObject.method2()())//上下文对象 const innerArrowFunction=contextObject.method2(); console.log(innerArrowFunction())// contextObject(上下文对象)
Javascript的 这
简单函数调用
函数foo(){ console.log(“bar”); console.log(this); } foo();// 调用函数
对对象调用函数
var myObj={key:“Obj”}; myObj.logThis=函数(){ //我是一种方法 console.log(this); } myObj.logThis();// myObj已被记录
//继续前面的代码片段 var myVar=myObj.logThis; myVar(); //根据操作模式记录窗口/全局/未定义
var el=文档.getElementById('idOfEl'); el.addEventListener('click',function(){console.log(this)}); //addEventListener调用的函数将此作为元素的引用 //所以点击元素就会记录该元素本身
这个 新的
关键字
职能人员(姓名){ this.name=名称; this.sayHello=函数(){ console.log(“Hello”,this); } } var awal=新人员(“awal”); awal.sayHello(); //在`awal.sayHello`中,`this`包含对变量`awal的引用`
使用调用函数 新的 关键字将立即初始化 对象 类型为 人 . 此的构造函数 对象 将其构造函数设置为 人 此外,请注意 水洼类型 会回来的 对象 只有。 这个新的 对象 将分配给 人员.原型 。这意味着 人 原型将可用于的所有实例 人 ,包括 阿瓦尔 . 功能 人 自身现在被调用; 这 是对新构建对象的引用 阿瓦尔 .
在函数上调用函数: 呼叫
和 应用
函数foo(){console.log(this,arguments);} var thisArg={myObj:“很酷”}; foo.call(thisArg,1,2,3);
foo.apply(thisArg,[1,2,3])
呈现。。。。 绑定
!
函数foo(a,b){ console.log(this,参数); } var thisArg={myObj:“现在更酷了”}; var绑定=foo.bind(thisArg,1,2); console.log(绑定类型);// 日志`函数` console.log(绑定); /*日志`函数(){本机代码}`*/ bound();// 调用`.bind返回的函数` //logs`{myObj:“现在更酷了”},[1,2]`
额外的东西,复制这个
var myObj={ 您好:函数(){ 返回“世界” }, myMethod:函数(){ //复制这个,变量名是区分大小写的 var that=这个; //回调ftw\o/ foo.bar(“args”,函数(){ //我想在这里打“你好” this.hello();// 错误 //但‘这’指的是‘foo’该死! //哦,等等,我们有备份/ this.hello();// “世界” }); } };
保存在中的内容 这 默认情况下? 如果我们用Object-dot符号将函数作为方法调用会怎么样? 如果我们使用 新的 关键词? 我们如何操作 这 具有 呼叫 和 应用 ? 使用 绑定 . 正在复制 这 解决嵌套范围问题。
(函数(值){ this.value=值; $('.some-elements').each(函数(elt){ elt.innerHTML=this.value;// 哦!! 可能未定义 }); })(2);
this.value=值;
(函数(值){ var self=这个;// 零钱 self.value=值; $('.some-elements').each(函数(elt){ elt.innerHTML=self.value;// 呸!!== 2 }); })(2);
-
6 -
6 基本值本身似乎有一些方法,如String#substring()、Number#toString()等。因此,可能与那篇文章的命名不同,它们的行为实际上就像是对象一样(它们都是原型,即String#substring()实际上是:String.prototype.substring=function(){…})。 如果我错了,请纠正我。 – 阿伦吉辛 评论 2010年7月4日16:49 -
12 -
1 -
9 这 并不完全是关于范围的。 这一切都与执行上下文有关,这与范围不同。 JavaScript在词汇上有范围(意思是范围由代码的位置决定),但 这 取决于如何调用包含它的函数,而不是该函数位于何处。 – 斯科特·马库斯 评论 2016年3月16日5:00
的价值如何 这
决心?
var人={ 名字:“佩内洛普”, lastName:“巴里摩尔”, fullName:函数(){ //我们使用“this”就像上面的句子一样: console.log(this.firstName+“”+this.lastName); //我们还可以写: console.log(person.firstName+“”+person.lastName); } }
什么决定了未来
函数foo(){ //返回箭头函数 返回(a)=>{ //`this`这里是从`foo()词汇继承而来的` console.log(this.a); }; } 变量obj1={a:2}; 变量obj2={a:3}; var bar=foo.call(obj1); 酒吧呼叫(obj2);// 2,而不是3!
此对象原型(&O) 作者:凯尔·辛普森。 ©2014 Getify解决方案。 javascriptissexy.com- 网址:http://goo.gl/pvl0GX 安格斯·克罗尔- 网址:http://goo.gl/Z2RacU
函数someKindOfFunction(){ this.style='foo'; }
如何调用函数(包括作为对象方法,使用 呼叫 和 应用 ,使用 新的 ) 的使用 绑定 箭头功能的词汇(它们采用 这 外部执行上下文) 代码是处于严格模式还是非严格模式 是否使用调用了代码 评估
-
9 -
@非常感谢。 在js中,最令人困惑的是,在前面使用的所有语言(c、c++)中,这是无法操作的,n始终指向对象实例,而在js里,这取决于并可以在使用 函数调用 , 函数绑定 等–苏希尔 – 苏希尔 评论 2013年6月25日10:04 -
2 这 做 不 引用函数的范围。 这 将引用特定对象(或可能 未定义 ),正如您所说,可以使用更改 .call() 或 .apply() .A函数的 范围 本质上是(简化后)它可以访问哪些变量,这完全取决于函数的声明位置,并且不能更改。 – nnnnnn 评论 2015年1月3日22:48 -
@Pointy(点): “说每个函数调用都有一个作用域更为正确。” 更正确的说法是函数(和现在的块)具有 范围 ,函数 电话 有 上下文 .Scope定义了该范围内的代码可以使用的标识符。 上下文定义了这些标识符绑定到的内容。 – T.J.克劳德 评论 2015年11月14日15:09 -
1 “无论该范围是什么,都由”this“引用。” 不, 这 在ES5和之前(例如,在编写此答案时),范围与彼此无关。 在ES2015(又名ES6)中, 这 和范围是相关的 一 相当小的wrt箭头函数( 这 中的箭头函数继承自其封闭范围),但 这 从不提及范围。 – T.J.克劳德 评论 2015年11月14日15:09
el.onclick=foo;// 在foo-obj中 el.onclick=函数(){this.style.coolor='#fff';}//obj el.onclick=function(){doSomething();}//在doSometing中- 窗口 foo-obj中的el.addEventListener('click',foo,false)// el.attachEvent('onclick,function(){//this}')//窗口,所有 符合IE:) <button onclick=“this.style.color='#fff';”>//obj <button onclick=“foo”>//在foo窗口中,但您可以 onclick=“foo(this)”>
全球这个 在浏览器中,在全局范围内, 这 是 窗口 对象 <script type=“text/javascript”> console.log(这个===窗口);// 真的 var foo=“bar”; console.log(this.foo);// “酒吧” console.log(window.foo);// “酒吧” 在 节点 使用repl, 这 是顶级命名空间。 您可以将其称为 全球的 . >这个 {ArrayBuffer:[函数:ArrayBuffer], Int8Array:{[函数:Int8Array]BYTES_PER_ELEMENT:1}, Uint8Array:{[函数:Uint8Array]BYTES_PER_ELEMENT:1}, ... >全局===此 真的 在 节点 从脚本执行, 这 在全局范围开始时是一个空对象。 它与 全球的 \\测试.js console.log(this);\\ {} console.log(这===全局);\\ 法斯莱 函数this
<script type=“text/javascript”> foo=“bar”; 函数testThis(){ this.foo=“foo”; } console.log(this.foo)// 日志“栏” testThis(); console.log(this.foo)// 日志“foo” </script>
<script type=“text/javascript”> foo=“bar”; 函数testThis(){ “使用严格”; this.foo=“foo”; } console.log(this.foo)// 日志“栏” 测试This()// Uncaught TypeError:无法设置未定义的属性“foo” </script>
<script type=“text/javascript”> foo=“bar”; 函数testThis(){ this.foo=“foo”; } console.log(this.foo)// 日志“栏” 新测试This(); console.log(this.foo)// 日志“栏” console.log(新testThis().foo)// 日志“foo” </script>
这个原型
函数Thing(){ console.log(this.foo); } Thing.prototype.foo=“bar”; var thing=新事物()// 日志“栏” console.log(thing.foo)// 日志“栏”
函数Thing(){ this.things=[]; } var thing1=新事物(); var thing2=新事物(); thing1.things.push(“foo”); console.log(thing1.things)// 日志[“foo”] console.log(thing2.things)// 日志[]
反对这个
var对象={ foo:“bar”, logFoo:函数(){ console.log(this.foo); } }; obj.logFoo()// 日志“栏”
DOM事件this
函数Listener(){ document.getElementById(“foo”).addEventListener(“点击”, this.handleClick); } Listener.prototype.handleClick=函数(事件){ console.log(this)// 日志“<div id=”foo“></div>” } var listener=新监听器(); document.getElementById(“foo”).click();
函数Listener(){ document.getElementById(“foo”).addEventListener(“点击”, this.handleClick.bind(this)); } Listener.prototype.handleClick=函数(事件){ console.log(this)// 日志侦听器{handleClick:function} } var listener=新监听器(); document.getElementById(“foo”).click();
HTML此
<div id=“foo”onclick=“console.log(this);”></div> <script type=“text/javascript”> document.getElementById(“foo”).click()// 日志<div id=“foo”。。。 </script>
评估这个
函数Thing(){ } Thing.prototype.foo=“bar”; Thing.prototype.logFoo=函数(){ eval(“console.log(this.foo)”)// 日志“栏” } var thing=新事物(); thing.logFoo();
用这个
函数Thing(){ } Thing.prototype.foo=“bar”; Thing.prototype.logFoo=函数(){ 用(这个){ console.log(foo); foo=“foo”; } } var thing=新事物(); thing.logFoo();// 日志“栏” console.log(thing.foo);// 日志“foo”
j查询此
<div class=“foo bar1”> <div class=“foo bar2”> <script type=“text/javascript”> $(“.foo”).each(函数(){ console.log(this)// logs<div class=“foo。。。 }); $(“.foo”).on(“单击”,函数(){ console.log(this)// logs<div class=“foo。。。 }); $(“.foo”).each(函数(){ this.click(); }); </script>
全球的 (即所有功能之外) 内部直接“非绑定函数”调用 (即具有 还没有 受呼叫约束 函数名称.bind ) 内部间接“非绑定函数”调用 通过 函数名称.call 和 functionName.应用 内部“绑定函数”调用 (即一个函数 已绑定 通过呼叫 函数名称.bind ) 通过“新建”创建对象时 内联DOM事件处理程序内部
全球背景 (即在所有功能之外): 在所有功能之外(即在全球范围内) “当前 对象” (因此 “这个” )总是 “窗口” 对象。 内部直接“非绑定函数”调用 : 在直接的“非绑定函数”调用中, 对象 被调用的函数调用成为“当前对象” (因此 的价值 “这个” ). 如果调用函数时没有显式 当前对象 ,的 当前对象 要么是 “窗口” 对象(对于非严格模式)或 未定义 (对于严格模式)。 中定义的任何函数(或变量) 全球背景 自动成为的属性 “窗口” 对象。 例如,假设函数在全局上下文中定义为 函数UserDefinedFunction(){ 警报(this) } 它成为窗口对象的属性,就像您定义了 它是作为 窗口。 UserDefinedFunction=函数(){ 警报(this) } 在“非严格模式”中,直接通过 “用户定义函数()” 将自动调用 它是作为 “window.UserDefinedFunction()” 制作 “窗口” 作为 “当前对象” (因此 “这个” )在 “用户定义函数” 。在“非严格模式”下调用此函数将导致以下结果 UserDefinedFunction()//显示[object Window],因为它会自动作为窗口调用。 用户定义的函数() 在“严格模式”中,直接通过 “用户定义函数()” 将 “不” 自动调用它 “window.UserDefinedFunction()” 。因此 “当前 对象” (以及 “这个” )在 “用户定义函数” 应为 未定义 。在“严格模式”下调用此函数将导致以下结果 UserDefinedFunction()//显示未定义 然而,使用窗口对象显式调用它将导致 以下内容 窗口。 UserDefinedFunction()//“无论模式如何,始终显示[object Window]。” 让我们看另一个例子。 请查看以下代码 函数UserDefinedFunction() { 警告(this.a+“,”+this.b+“,“+this.c+”,“+this.d) } 变量o1={ a: 1、, b: 2、, f: 用户定义函数 } 无功氧气={ c: 3、, d: 4、, f: 用户定义函数 } o1.f()//应显示1,2,未定义,未定义 o2.f()//应显示未定义、未定义、3,4 在上面的例子中,我们看到,当 “用户定义函数” 是 通过调用 o1号机组 , “这个” 取值为 o1号机组 和 其属性的值 “a” 和 “b” 显示。 价值观 属于 “c” 和 “d” 显示为 未定义 作为 o1号机组 做 不定义这些属性 类似地,当 “用户定义函数” 通过调用 氧气 , “这个” 取值为 氧气 及其属性的价值 “c” 和 “d” 显示。 的价值 “a” 和 “b” 显示为 未定义 作为 氧气 没有定义这些属性。 内部间接“非绑定函数”调用 通过 函数名称.call 和 functionName.应用 : 当 “非绑定函数” 通过调用 函数名称.call 或 functionName.应用 ,的 “当前对象” (因此 “这个” )设置为的值 “这个” 传递给的参数(第一个参数) 调用/应用 。下面的代码演示了相同的内容。 函数UserDefinedFunction() { 警告(this.a+“,”+this.b+“,“+this.c+”,“+this.d) } 变量o1={ a: 1、, b: 2、, f: 用户定义函数 } 无功氧气={ c: 3、, d: 4、, f: 用户定义函数 } UserDefinedFunction.call(o1)//应显示1,2,undefined,undefine UserDefinedFunction.apply(o1)//应显示1,2,undefined,undefine UserDefinedFunction.call(o2)//应显示未定义、未定义、3,4 UserDefinedFunction.apply(o2)//应显示未定义、未定义、3,4 o1.f.call(o2)//应显示未定义、未定义、3,4 o1.f.apply(o2)//应显示未定义、未定义、3,4 o2.f.call(o1)//应显示1,2,未定义,未定义 o2.f.应用(o1)//应显示1,2,未定义,未定义 上述代码清楚地表明,任何“NON”的“this”值 绑定函数”可以通过 调用/应用 此外,如果 “这个” 参数未显式传递给 调用/应用 , “当前对象” (因此“this”的值)设置为 “窗口” 非严格模式和 “未定义” 严格模式下。 内部“绑定函数”调用 (即通过调用绑定的函数 函数名称.bind ): 绑定函数是其 “这个” 值已被 固定的。 下面的代码演示了如何 “这个” 在情况下工作 绑定函数的 函数UserDefinedFunction() { 警告(this.a+“,”+this.b+“,“+this.c+”,“+this.d) } 变量o1={ a: 1、, b: 2、, f: 用户定义函数, bf:空 } 无功氧气={ c: 3、, d: 4、, f: 用户定义函数, bf:空 } var bound1=用户定义函数绑定(o1);// 将函数“bound1”的“this”值永久修复为对象o1 bound1()//应显示1,2,未定义,未定义 var bound2=UserDefinedFunction.bind(o2);// 将函数“bound2”的“this”值永久固定到Object o2 bound2()//应显示未定义、未定义、3,4 var bound3=o1.f.bind(o2);// 将函数“bound3”的“this”值永久固定到Object o2 bound3()//应显示未定义、未定义、3,4 var bound4=o2.f.bind(o1);// 将函数“bound4”的“this”值永久修复为对象o1 bound4()//应显示1,2,undefined,undefine o1.bf=UserDefinedFunction.bind(o2)//永久性地将函数“o1.bf”的“this”值修复为对象o2 o1.bf()//应显示未定义、未定义、3,4 o2.bf=UserDefinedFunction.bind(o1)//永久地将函数“o2.bf”的“this”值修复到对象o1 o2.bf()//应显示1,2,未定义,未定义 bound1.call(o2)//仍应显示1,2,undefined,undefine。 “call”无法更改绑定函数的“this”值 bound1.apply(o2)//仍应显示1,2,undefined,undefine。 “apply”无法更改绑定函数的“this”值 o2.bf.call(o2)//仍应显示1,2,undefined,undefine。 “call”无法更改绑定函数的“this”值 o2.bf.apply(o2)//仍应显示1,2,未定义,未定义。 “apply”无法更改绑定函数的“this”值 如上述代码所示, 任何“绑定函数”的“this”值 无法通过调用/应用更改 此外,如果 “这个” 参数未显式传递给绑定, “当前对象” (因此 “这个” )设置为 “窗口” 在非 严格模式和 “未定义” 严格模式下。 还有一件事。 绑定已绑定的函数不会更改 “这个” . 它仍被设置为第一个绑定函数设置的值。 通过“新建”创建对象时 : 在构造函数中 “当前对象” (因此 “这个” )引用当前正在创建的对象 通过 “新” 无论函数的绑定状态如何。 然而 如果构造函数是绑定函数,则应使用调用 为绑定函数设置的预定义参数集。 内联DOM事件处理程序内部 : 请查看以下HTML代码段 Hello World你好世界 <div style='宽度:100px; 高度:100px;' onclick='OnDivClick(event,this)'>你好世界 这个 “这个” 在上述示例中,请参考“button”元素和 “div”元素。 在第一个示例中,按钮的字体颜色应设置为 单击时为白色。 在第二个示例中,当 “div”(div) 元素被单击,则应 打电话给 OnDivClick上 函数及其第二个参数 引用单击的div元素。 然而 “这个” 在OnDivClick中 不得 引用单击的 分区 元素。 应设置为 “窗口对象” 或 “未定义” 在里面 非严格要求 和 严格模式 分别(如果 OnDivClick上 是一个 未绑定函数 )或设置为预定义 绑定值(如果 OnDivClick上 是一个 有界函数 )
在全球范围内 “这个” 总是指 “窗口” 对象 无论何时调用函数,都会在 对象( “当前对象” ). 如果 当前对象 未明确提供, 这个 当前对象 是 “窗口对象” 在里面 非严格 模式 和 “未定义” 默认情况下为严格模式。 的价值 “这个” 在非绑定函数中是对调用函数的上下文中的对象的引用( “当前对象” ) 的价值 “这个” Non-Bound函数中的 呼叫 和 应用 函数的方法。 的价值 “这个” 对于Bound函数是固定的,不能 被覆盖 呼叫 和 应用 函数的方法。 绑定和已绑定的函数不会更改“this”的值。 它仍被设置为第一个绑定函数设置的值。 的价值 “这个” 构造函数中的对象 创建并初始化 的价值 “这个” 内联DOM事件处理程序内是引用 为其提供事件处理程序的元素。
在哪里
这 取自 ?
功能如何 已调用 ?
有什么价值
这 箭头函数所在的位置 定义 ?
这个 这 引用总是指 object—一个单数对象,通常在函数或 方法,尽管它可以在全局 范围。 请注意,当我们使用strict模式时,它保存的值为 在全局函数和未定义的匿名函数中未定义 绑定到任何对象。
当我们传递一个方法(它使用 这 )作为要用作回调函数的参数。 当我们使用内部函数(闭包)时。 需要注意的是,闭包不能访问外部函数的 这 变量,因为此变量只能由函数本身访问,而不能由内部函数访问。 当依赖于 这 被分配给跨上下文的变量,在这种情况下 这 引用了另一个与最初预期不同的对象。 使用时 这 以及绑定、应用和调用方法。
var val=“window.val” var对象={ val:“obj.val”, innerMethod:函数(){ var val=“obj.val.inner”, func=函数(){ var self=此; 返回self.val; }; 返回函数; }, 路由方法:函数(){ 返回this.val; } }; //这实际上是在窗口对象内部执行的 console.log(obj.innerMethod())// 返回window.val //细分为2行详细说明了这一点 var_inn=对象内部方法(); 控制台.log(_inn())// 返回window.val 控制台.log(obj.outerMethod())// 返回obj.val
调用对象的方法
var状态=1; var帮助器={ 状态:2, getStatus:函数(){ 返回this.status; } }; var theStatus1=助手.getStatus()// 第1行 console.log(状态1)// 2 var theStatus2=helper.getStatus; console.log(状态2())// 1
与构造函数一起
职能人员(姓名){ this.personName=名称; this.sayHello=函数(){ return“Hello”+this.personName; } } var person1=新人员(“Scott”); console.log(person1.sayHello())// 你好,斯科特 var person2=新人员(“Hugh”); var sayHelloP2=person2.sayHello; console.log(sayHelloP2())// 你好,未定义
函数调用
函数testFunc(){ this.name=“名称”; this.myCustomAttribute=“自定义属性”; 返回此; } var whatIsThis=testFunc(); 控制台.log(whatIsThis)// 窗口 var whatIsThis2=新的testFunc(); 控制台.log(whatIsThis2)// testFunc()/object console.log(window.myCustomAttribute)// 自定义属性
使用事件处理程序
<script type=“application/javascript”> 函数click_handler(){ 警告(this);// 警告窗口对象 } </script> 单击我</ 按钮>
您还可以使用 .apply() .call() 和 .bind() JQuery代理是另一种可以用来确保函数中的值符合要求的方法。 (检查 理解$.proxy() , jQuery.proxy()用法 ) 什么是 var that=这个 在JavaScript中表示
功能车(品牌、型号、年份){ var this={};// 可以说,在引擎盖下 this.make=品牌; this.model=模型; this.year=年; 返回此;// 发动机罩下面 } var mycar=新车(‘Eagle’,‘Talon TSi’,1993); //============发动机罩下 变量this={}; this.make=“鹰”; this.model=“泰龙TSi”; this.year=1993年; 返回此;
console.log(this)
console.log(this===窗口)//真
console.log(this===module.exports)//真 console.log(this===导出)//true
functionObject.call(objectForThis,arg0,arg1,arg2,…);
函数foo(){ console.log(this); } foo();// 这是窗口对象
foo();
foo.call(窗口);
'使用严格'; 函数foo(){ console.log(this); } foo();// 这是窗口对象
foo();
foo.call(未定义);
常数bar={ name:'bar', foo(){ console.log(this); }, }; bar.foo();// 这是酒吧
常数bar={ name:'bar', fn1(){console.log(this);}, fn2:function(){console.log(this);}, fn3:其他功能, }; 函数otherFunction(){console.log(this)}; bar.fn1();// 这是酒吧 bar.fn2();// 这是酒吧 bar.fn3();// 这是酒吧
{恒定温度=bar.fn1;温度调用(bar);} {恒定温度=bar.fn2;温度调用(bar);} {恒定温度=bar.fn3;温度调用(bar);}
函数foo(){ console.log(this); } 函数栏(){ const对象ForThis={名称:'moo'} foo.call(objectForThis);// 显式传递objectForThis } 常量对象={ 巴, }; obj.bar()对象;
函数foo(){ console.log(this); } const-bar=foo.bind({name:'moo'}); //bind创建了一个新的不可见函数,该函数使用绑定对象调用foo。 bar(); //此处传递给bar的objectForThis被忽略,因为 //bind创建的不可见函数将使用调用foo //我们在上面绑定的对象 bar.call({name:其他});
函数绑定(fn,objectForThis){ 返回函数(…args){ return fn.call(objectForthis,…args); }; }
函数foo(){ console.log(this); } const bar=绑定(foo,{名称:'abc'});
consta=()=>{console.log(this)};
consttempFn=function(){console.log(this)}; const a=tempFn.bind(this);
consta=()=>{console.log(this);}//这是全局对象
'使用严格'; consta=()=>{console.log(this);}//这是未定义的
函数foo(){ return()=>{console.log(this);} } 常量对象={ foo、, }; 常量b=obj.foo(); b();
函数foo(){ 函数tempFn(){ console.log(this); } return tempFn.bind(this); } 常量对象={ foo、, }; 常量b=obj.foo(); b.调用(如果是严格模式,则为窗口或未定义);
functionName.apply(objectForThis,arrayOfArgs);
functionName.call(objectForThis,…arrayOfArgs);
每次执行函数时都会创建此属性,而不是 在此之前。 它的值不是静态的,而是取决于它的使用方式。 采用一个值,该值指向其所在函数的所有者 习惯于
-
这个 接受的答案 这里是正确的、最新的和完整的。 代码示例不应该以屏幕截图的形式出现,而是作为可复制的代码块(也适用于您之前的答案)。 “此属性是在每次执行函数时创建的,而不是在此之前创建的” 不正确:它缺少类和全局执行上下文。 “取决于它的使用方式” 非常模糊。 “函数所有者” 在JS中不是真正的语言构造。 对象不能“调用”方法。 可以调用方法 在 (或“关闭”)对象。 “正常模式”更少 正常的 比严格模式… – 塞巴斯蒂安·西蒙 评论 2021年11月30日18:07 -
一般来说, 全球This 应该提到而不是 窗口 . “箭头函数没有自己的此属性” 是模糊的。 这 不是对象的属性(ES语言值),而是环境记录上的内部插槽(ES规范值)。 箭头函数不 绑定 这 . “如果它们是在全局级别定义的” ,则适用严格模式与宽松模式的相同规则。 事件监听器实际上并不特别; 添加事件侦听器 使用调用侦听器函数 这 绑定到 当前目标 收到的事件的属性。 – 塞巴斯蒂安·西蒙 评论 2021年11月30日18:08 -
-
@塞巴斯蒂安·西蒙,我真的很尊重你花时间阅读我的答案。 我真的很感激你最新的回答。 但我认为它对初学者没有多大用处,因为它太长了,而且,如果我想要一个详细的概念,我会去看官方的MDN文档。 我尽可能简短地回答。 提供的屏幕截图只是为了快速查看,以后我也会尝试放置代码。 – 阿勒姆·乔杜里 评论 2021年12月1日3:46
<script type=“text/javascript”language=“javascript“> $('#tbleName tbody tr').each(函数{ var txt=“”; txt+=$(this).find(“td”).eq(0).text(); \\同上,但synatx不同 var txt1=“”; txt1+=$('#tbleName tbody tr').eq(0).text(); 警报(txt1) }); </script>
总结 这
Java脚本:
的价值 这 取决于 函数是如何调用的,不是在哪里创建的! 通常 这 由点左边的对象确定。 ( 窗口 在全球空间) 事件侦听器中 这 指调用事件的DOM元素。 使用调用in函数时 新的 关键字的值 这 指新创建的对象 您可以操作 这 具有以下功能: 呼叫 , 应用 , 绑定
例子:
let对象={ prop1:function(){console.log(this);} } object.prop1();// 物体在点的左边,所以这是物体 const myFunction=object.prop1//我们将函数存储在变量myFuncton中 myFunction();// 我们在全球空间 //myFunction是全局对象上的属性 //因此它记录窗口对象
事件侦听器示例:
document.querySelector('.foo').addEventListener('click',function(){ console.log(this);// 这是指调用eventListener的DOM元素 }) document.querySelector('.foo').addEventListener('单击',()=>{ console.log(this);// 提示,es6箭头函数没有自己绑定到此v })//因此,这将记录全局对象
.foo:悬停{ 颜色:红色; 光标:指针; }
单击我
示例构造函数:
职能人员(姓名){ this.name=名称; } const me=新人(“维伦”); //当使用new关键字时,构造函数中的this将引用新创建的对象 console.log(我的名字); //因此,name属性被放置在使用new关键字创建的对象上。
<脚本> console.log('这是什么:'+这); console.log(this); </script>
<脚本> 函数myFunc(){ console.log('这是什么:'+这); console.log(this); } myFunc(); </script>
<脚本> var firstName=“诺拉”; var lastName=“Zaman”; var myObj={ 名字:“主”, 姓:“男爵”, 打印名称获取上下文:函数(){ console.log(firstName+“”+lastName); console.log(this.firstName+“”+this.lastName); 返回此; } } var context=myObj.printNameGetContext(); console.log(上下文); </script>
<body> <button class=“btn”>点击我</button> <脚本> 函数printMe(){ //Terminal2:此函数在窗口上下文中声明,因此此函数属于窗口对象。 console.log(this); } document.querySelector('.btn').addEventListener('click',function(){ //Terminal1:按钮上下文,此回调函数属于DOM元素 console.log(this); printMe(); }) </script> </body>
<脚本> var myObj={ 名字:“主”, 姓:“男爵”, printName:函数(回调1,回调2){ //使用此myObj上下文附加回调1 this.callback1=回调1; this.callback1(this.firstName+“”+this.lastName) //我们没有用myObj附加callback2,所以默认情况下它是带有窗口上下文的reamin 回调2(); /* //测试以下代码 this.callback2=回调2; this.callback2(); */ } } var回调2=函数(){ console.log(this); } myObj.printName(函数(数据){ console.log(数据); console.log(this); },回调2); </script>
var color='red';// 窗口的属性 var对象={ color:'blue',//窗口属性 printColor:function(){//obj的属性,与obj一起附加 var self=此; console.log('打印颜色中--this.color:'+this.color); console.log('In-printColor-self.color:'+self.color); (function(){//decleard在printColor内部,但不是对象的属性,它将在窗口上下文中执行。 console.log(this) console.log('在IIFE中--this.color:'+this.color); console.log('In IIFE--self.color:'+self.coolor); })(); 函数nestedFunc(){//declead在printColor内部,但不是对象的属性,它将在窗口上下文上执行。 console.log('nested-fun--this.color:'+this.color); console.log('nested-fun--self.color:'+self.color); } 嵌套函数();// 在窗口上下文中执行 return nestedFunc; } }; 对象打印颜色()();// 在窗口上下文上执行的返回函数 </script>