JavaScript this介绍
发布时间:2023-03-10 09:24:24 所属栏目:教程 来源:
导读:当前执行代码的环境对象,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。(MDN)
this 指向的是当前的代码上下文环境,所以不同情况下的 this 指向也不同。
1. 全局下的 this
在全局环境下,th
this 指向的是当前的代码上下文环境,所以不同情况下的 this 指向也不同。
1. 全局下的 this
在全局环境下,th
当前执行代码的环境对象,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。(MDN) this 指向的是当前的代码上下文环境,所以不同情况下的 this 指向也不同。 1. 全局下的 this 在全局环境下,this 指向全局对象。 全局对象和宿主环境相关,在浏览器下,全局对象就是 window 对象,在 node.js 中,全局对象是 global 对象。 window === this; // 输出:true 新的标准提供了 globalThis 关键字来获取全局对象,这样就能抹平宿主的差异来操作处理全局对象了。 2. 函数中的 this 函数在不同情况下,其 this 的指向也不同。 2.1 对象下的方法 方法也是一个函数,如果通过对象调用一个函数,函数的 this 就会指向这个对象。 var person = { age: , name: '鸽子王', skill: '放鸽子', say: function() { console.log('来一段自我介绍:'); console.log('我是' + this.name); console.log('我今年' + this.age + '岁'); console.log('我最擅长' + this.skill); }, }; person.say(); say函数作为对象下的方法,在被调用后,其 this 指向的是他所在的对象,在这里就是 person 对象。 2.2 原型链上方法的 this 原型链上的方法,this 指向的也是调用该方法的对象。 var __proto__ = { sum: function() { return this.number1 + this.number2; }, }; var object = Object.create(__proto__); object.number1 = ; object.number2 = ; console.log( object.sum(), ); // 输出:3 Object.create 做就就是将参数作为原型,创建一个对象。 所以 object 的第一原型就是 __proto__ 对象。 number1 和 number2 都是 object 变量的属性,但却可以被 sum 方法中的 this 访问到,所以在原型链的方法中,this 指向的就是调用该方法的对象。 2.3 getter / setter 下的 this getter 和 setter 下的 this 也会指向调用该 getter 和 setter 的对象。 var object = { _name: '鸽子王', get name() { return this._name; }, set name(val) { console.log(val); this._name = val; } }; console.log(object.name); // 输出:鸽子王 object.name = '鸽子天王'; // 输出:鸽子天王 console.log(object.name); // 输出:鸽子天王 getter 和 setter 本质上也可以理解成两个函数,作为对象下的函数,在调用的时候 this 也会指向该对象。 2.4 作为 DOM 节点的事件处理器 作为 DOM 节点的事件处理器的时,函数的 this 会指向这个 DOM 对象。 <div> <button>点击我</button> </div> <script> document.querySelector('button').addEventListener('click', function() { this.innerHTML = '被点击了!'; }); </script> 2.5 作为一个内联的事件处理器 内联的事件处理器,其 this 指向的是 DOM 节点自身。 <div> <button onclick="console.log(this); console.log(this === document.querySelector('button'))">点击我</button> </div> 这个规则有局限性,只有最外层的 this 符合这个规则。 <div> <button onclick="function test() { console.log(this) }; test();">点击我</button> </div> test 函数的 this 指向的是全局对象 window。 2.6 其他大部分情况下 排开上述的几个情况,剩下的函数大部分情况下在调用时,this 指向的是全局对象,在浏览器中就是 window 对象。 function fn() { console.log(this); console.log(this === window); } fn(); 这样调用函数,其 this 指向的就是 window 对象了。 有的时候可能会搞混以下情况: var object = { username: '咸鱼', fn: function() { console.log(this.username); function thisTest() { console.log(this.username); console.log(this === window); } thisTest(); }, }; object.fn(); 这里 thisTest 方法输出的 username 就会是个 undefined,因为他的 this 指向的是 window,因为他不属于 object 对象的一个方法,所以 this 就指向了 window。 在回调函数中经常会碰到这个问题: var info = { account: '123', password: '456', login: function(cb) { setTimeout(function() { cb({ account: this.account, password: this.password, }); }, ); } }; info.login(function(info) { console.log(info); }); 这里回调函数获取的账号和密码是 undefined,原因就是 this 的指向问题。 通常会使用保留上层 this 的方式解决这个问题。 var info = { account: '123', password: '456', login: function(cb) { var _this = this; setTimeout(function() { cb({ account: _this.account, password: _this.password, }); }, ); } }; info.login(function(info) { console.log(info); }); 这样就能解决这个问题。 另外一个情况也很容易混淆 this : var object = { user: 'no.1', say: function() { console.log(this.user); }, }; var say = object.say; object.say(); // 输出:"no.1" say(); // 输出:undefined 这是因为把 object 下的 say 方法单独赋值给 say 变量的时候,其就作为了 window 下的一个方法,所以他的 this 指向的是 window。 在严格模式中,这种情况下的 this 会变成 undefined。 2.7 构造函数 在 JavaScript 构造函数也被成为 对象构造器,用于产生对象。 构造函数的声明和普通函数几乎没有区别: function Point(x, y) { this.x = x; this.y = y; } var point = new Point(, ); console.log(point.x); // 输出:1 console.log(point.y); // 输出:2 构造函数使用 new 关键字来构造对象。所以当一个函数被使用 new 关键字调用时,这个函数就会作为一个构造函数。 在一个构造函数被调用后,其内部的 this 会指向一个对象,具体的内容可以参考 构造函数 章节。 3. 修改this 3.1 call 方法和 apply 方法 函数具有 call 方法和 apply 方法,这两个方法可以在调用函数的时候指定函数的 this。 var object = { user: 'no.1', }; function say() { console.log(this.user); } say(); // 输出:undefined say.call(object); // 输出:"no.1" say.apply(object); // 输出:"no.1" 通过 call 和 apply 方法将 say 函数执行时候的 this 设置为 object 对象。 call 方法从第二个参数开始,表示是要传递给当前函数的参数。 var object = { user: 'no.1', }; function fn(arg1, arg2, arg3) { console.log( this, arg1, arg2, arg3, ); } fn.call(object, , , ); apply 的第二个参数是个数组,数组里面的项会按数组的顺序作为参数传递给函数。 var object = { user: 'no.1', }; function fn() { console.log( this, arguments, ); } fn.apply(object, [, , ]); 通过 arguments 关键字就可以看到当前函数的参数,通常在需要修改 this ,又不确定参数的情况下,会使用 apply 来修改 this。 3.2 bind bind 方法用于给一个函数永久绑定一个指定的 this,bind 不会修改原函数,会返回一个新的函数。 var obj1 = { value: '今天打砖' }; var obj2 = { value: '明天打转' }; var fn = function() { console.log(this); }; var bindFn1 = fn.bind(obj1) var bindFn2 = bindFn1.bind(obj2); bindFn1(); bindFn2(); 可以看到 bindFn1 被绑定了 obj1 作为 this,之后不论怎么操作,他的 this 都会是 obj1。 bind 还有更多灵活的用法,参数也可以绑定,有关 bind、call、apply 这三个方法的更详细的信息可以查阅对应的文档。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |