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 这三个方法的更详细的信息可以查阅对应的文档。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
