JS中this是什么
理解this之前, 先纠正一个观点,this 既不指向函数自身,也不指函数的词法作用域。
如果仅通过this的英文解释,太容易产生误导了。
它实际是在函数被调用时才发生的绑定,也就是说this具体指向什么,取决于你是怎么调用的函数。也就是说谁调用的this,this就指向谁
JS中this说明
ES6中的箭头函数采用的是词法作用域。
为什么要使用this:使API设计得更简洁且易于复用。
this即不指向自身,也不指向函数的词法作用域。
this的指向只取决于函数的调用方式
this绑定规则
new > 显示绑定 > 隐式绑定 > 默认绑定
默认绑定
当独立函数调用时,不管是否在调用栈中,this都指向全局对象(浏览器中为window)
严格模式下,不能将全局对象用于默认绑定。
var a = 2; function foo(){ console.log(this.a); } function bar(){ var a = 5; foo(); } bar(); // 2
隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
对象属性引用链中只有最后一层在调用位置中起作用。
要求:对象内部必须包含一个指向函数的属性,该对象可通过这个属性间接引用函数。
function foo() { console.log( this.a ); } var obj2 = { a: 42, foo: foo }; var obj1 = { a: 2, obj2: obj2 }; obj1.obj2.foo(); // 42
隐式丢失
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // 这里bar将引用foo函数本身,所以不带有函数对象的上下文 var a = "oops, global"; // a是全局对象的属性 bar(); // "oops, global"
和回调函数的情况下(参数传递时的隐式赋值)
function foo() { console.log( this.a ); } function doFoo(fn) { // 参数传递时,相当于fn = obj.foo,就和上个例子一样了 fn(); // <-- call-site! } var obj = { a: 2, foo: foo }; var a = "oops, global"; // `a` also property on global object doFoo( obj.foo ); // "oops, global"
显式绑定
采用call()和apply(),通过传入一个对象(若为基本类型,会被封装函数转为对象—装箱),将this绑定到该对象。
硬绑定
function foo() { console.log( this.a ); } var obj = { a: 2 }; var bar = function() { foo.call( obj ); }; bar(); // 2 setTimeout( bar, 100 ); // 2 // 硬绑定后bar无论怎么调用,都不会影响foo函数的this绑定 bar.call( window ); // 2
硬绑定的典型应用是如下的包裹函数:
function foo(something) { console.log( this.a, something ); return this.a + something; } var obj = { a: 2 }; var bar = function() { return foo.apply( obj, arguments ); // 将obj对象硬编码进去 }; var b = bar( 3 ); // 2 3 console.log( b ); // 5
即将内部函数用apply硬绑定到某个对象,无论怎么调用这个包裹函数,都不会影响内部函数的this。
bind辅助函数如下:
function foo(something) { console.log( this.a, something ); return this.a + something; } // simple `bind` helper function bind(fn, obj) { return function() { return fn.apply( obj, arguments ); // 利用参数将obj传入进去 }; } var obj = { a: 2 }; var bar = bind( foo, obj ); // bind( foo, obj )会返回一个包裹函数 var b = bar( 3 ); // 2 3 console.log( b ); // 5
总结:上述包裹函数,想要包裹其他函数,只能一个一个重复写,硬编码的方式导致不能被重用,当某种功能需要多次重复使用时,将其抽象出来,成为函数。
new绑定
任何函数都可能被用作构造函数,当函数被new操作符“构造调用”时,会执行下面操作:
1. 创建一个新对象(若该函数不是JS内置的,则创建一个新的Object对象);
2. 将this绑定到这个对象;
3. 执行构造函数中的代码(为这个新对象添加属性);
4. 若函数没有返回其他对象,则自动返回这个新对象;若函数有return返回的是非对象,则还是自动返回这个新对象,即覆盖那个非对象。
function foo(a) { this.a = a; } var bar = new foo( 2 ); console.log( bar.a ); // 2
补充说明
间接引用
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2,由于p.foo = o.foo的返回值是目标函数的引用,所以调用位置是foo(),而不是p.foo()或o.foo()
箭头函数:不使用这四个this规则,根据词法作用域来决定this。
function foo() { // 返回一个箭头函数 return (a) => { // `this` here is lexically adopted from `foo()` console.log( this.a ); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; // foo()不是箭头函数,他的this被绑定到obj1 var bar = foo.call( obj1 ); // foo.call( obj1 )返回箭头函数,所以bar为箭头函数 bar.call( obj2 ); // 2! 箭头函数的this无法被修改,new也不行
如下为和箭头函数一样的模式:
function foo() { var self = this; // lexical capture of `this` setTimeout( function(){ console.log( self.a ); }, 100 ); } var obj = { a: 2 };
更多关于JS中this对象的相关文章大家可以点击下面的相关链接
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]