您好,欢迎访问一九零五行业门户网

了解Javascript中的this

为什么要写这篇文章?我之前在阿里面试,以及其它公司面试的时候曾经被问到过这个问题,所以想要分享给大家,如果你能清楚地知道下面 this 七种情况的区别,能跟面试官解释清楚,无疑是一个大大的加分项,理解完这篇文章,面试官再怎么问你 this 都不怕了。
谈及 javascript 中的 this,竟然让人觉得头疼,它不像 java,c++ 中的 this 指向调用 this 的该对象。
在函数中 this 到底取何值,是在函数真正被调用执行的时候确定下来的,函数定义的时候确定不了。
因为 this 的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。当你在代码中使用了 this,这个 this 的值就直接从执行的上下文中获取了,而不会从作用域链中搜寻。
关于 this 的取值,大体上可以分为以下七种情况:
情况一:全局 & 调用普通函数在全局环境中,this 永远指向 window。
console.log(this === window); //true
普通函数在调用时候(注意不是构造函数,前面不加 new),其中的 this 也是指向 window。
var x = 10; function foo(){ console.log(this); //window console.log(this.x); //10 } foo();
情况二:构造函数所谓的构造函数就是由一个函数 new 出来的对象,一般构造函数的函数名首字母大写,例如像 object,function,array 这些都属于构造函数。
function foo(){ this.x = 10; console.log(this); //foo {x:10} } var foo = new foo(); console.log(foo.x); //10
上述代码,如果函数作为构造函数使用,那么其中的 this 就代表它即将 new 出来的对象。
但是如果直接调用 foo 函数,而不是 new foo(),那就变成情况1,这时候 foo() 就变成普通函数。
function foo(){ this.x = 10; console.log(this); //window } var foo = foo(); console.log(foo.x); //undefined
情况三:对象方法如果函数作为对象的方法时,方法中的 this 指向该对象。
var obj = { x: 10, foo: function () { console.log(this); //object console.log(this.x); //10 } }; obj.foo();
注意:若是在对象方法中定义函数,那么情况就不同了。
var obj = { x: 10, foo: function () { function f(){ console.log(this); //window console.log(this.x); //undefined } f(); } } obj.foo();
可以这么理解:函数 f 虽然是在 obj.foo 内部定义的,但它仍然属于一个普通函数,this 仍指向 window。(这是个坑,要记牢)
在这里,如果想要调用上层作用域中的变量 obj.x,可以使用 self 缓存外部 this 变量。
var obj = { x: 10, foo: function () { var self = this; function f(){ console.log(self); //{x: 10} console.log(self.x); //10 } f(); } } obj.foo();
如果 foo 函数不作为对象方法被调用:
var obj = { x: 10, foo: function () { console.log(this); //window console.log(this.x); //undefined } }; var fn = obj.foo; fn();
obj.foo 被赋值给一个全局变量,并没有作为 obj 的一个属性被调用,那么此时 this 的值是 window。
情况四:构造函数 prototype 属性function foo(){ this.x = 10; } foo.prototype.getx = function () { console.log(this); //foo {x: 10, getx: function} console.log(this.x); //10 } var foo = new foo(); foo.getx();
在 foo.prototype.getx 函数中,this 指向的 foo 对象。不仅仅如此,即便是在整个原型链中,this 代表的也是当前对象的值。
情况五:函数用 call、apply或者 bind 调用。var obj = { x: 10 } function foo(){ console.log(this); //{x: 10} console.log(this.x); //10 } foo.call(obj); foo.apply(obj); foo.bind(obj)();
当一个函数被 call、apply 或者 bind 调用时,this 的值就取传入的对象的值。
情况六:dom event this在一个 html dom 事件处理程序里,this 始终指向这个处理程序所绑定的 html dom 节点:
function listener(){ document.getelementbyid('foo').addeventlistener('click', this.handleclick); //这里的 this 指向 listener 这个对象。不是强调的是这里的 this } listener.prototype.handleclick = function (event) { console.log(this); //<p id="foo"></p> } var listener = new listener(); document.getelementbyid('foo').click();
这个很好理解,就相当于是给函数传参,使 handleclick 运行时上下文改变了,相当于下面这样的代码:
var obj = { x: 10, fn: function() { console.log(this); //window console.log(this.x); //undefined } }; function foo(fn) { fn(); } foo(obj.fn);
你也可以用通过 bind 切换上下文:
function listener(){ document.getelementbyid('foo').addeventlistener('click',this.handleclick.bind(this)); } listener.prototype.handleclick = function (event) { console.log(this); //listener {} } var listener = new listener(); document.getelementbyid('foo').click();
前六种情况总结一句话为: this 指向调用该方法的对象。
情况七:箭头函数中的 this当使用箭头函数的时候,情况就有所不同了:箭头函数内部的 this 是词法作用域,由上下文确定。
var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); //object {x: 10} console.log(this.x); //10 } } } fn()()(); } } obj.foo();
现在,箭头函数完全修复了 this 的指向,this 总是指向词法作用域,也就是外层调用者 obj。
如果使用箭头函数,以前的这种 hack 写法:
var self = this;
就不再需要了。
var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); // object {x: 10} console.log(this.x); //10 } } } fn.bind({x: 14})()()(); fn.call({x: 14})()(); } } obj.foo();
由于 this 在箭头函数中已经按照词法作用域绑定了,所以,用 call()或者 apply()调用箭头函数时,无法对 this 进行绑定,即传入的第一个参数被忽略。
补充说明:this 为保留字,你不能重写 this。
function test(){ var this = {}; //uncaught syntaxerror: unexpected token this }
宿主对象:
一门语言在运行的时候,需要一个环境,叫做宿主环境。
对于javascript,宿主环境最常见的是 web 浏览器,浏览器提供了一个 javascript 运行的环境,这个环境里面,需要提供一些接口,好让 javascript 引擎能够和宿主环境对接。
javascript 引擎才是真正执行 javascript 代码的地方,常见的引擎有 v8(目前最快 javascript 引擎、google 生产)、javascript core。
在浏览器或者服务端( nodejs )都有自己的 js 引擎,在浏览器中,全局对象为 window,而在 nodejs 中,全局对象为 global。
以上就是了解javascript中的this的详细内容。
其它类似信息

推荐信息