ES6中setTimeout函数的this
在编程的过程中有同学遇到不太分明ES6中this
指向的问题,代码形象如下:
function myFunction(){ var mthis = this; setTimeout(()=>{ // this=mthis console.log('setTimeout中的this:', this) },100)}
this
是什么,是全局上下文window
吗?这里须要跟ES5
辨别一下。
ES6中箭头函数外部并没有 this
,this
会作为变量始终向下级词法作用域查找,直至找到为止。
先看一下几个相干的常识
函数的调用
function myFunction(a, b){ return a * b;}myFunction(2, 3)
输入后果的是6
以上myFunction
函数不属于任何对象。然而在 JavaScript
中,始终存在一种默认的全局对象。
在 HTML 中,默认全局对象是 HTML 页面自身,所有下面的函数“属于”HTML 页面。
在浏览器中,这个页面对象就是浏览器窗口。下面的函数主动成为一个窗口函数。
myFunction()
和 window.myFunction()
是同一个函数。
这是调用函数的常见办法,但并不是一个好习惯。
全局变量、办法或函数很容易在全局对象中产生命名抵触和破绽。
this 关键词
在 JavaScript
中,被称为 this
的事物,指的是“领有”以后代码的对象。
this
的值,在函数中应用时,是“领有”该函数的对象。
请留神 this
并不是变量。它属于关键词。您无奈扭转 this
的值。
全局对象
作为函数调用函数
当不带拥有者对象调用对象时,this
的值成为全局对象。
在 web 浏览器中,全局对象就是浏览器对象。
本例以 this
的值返回这个 window 对象:
示例
var x = myFunction(); // x 将成为 window 对象function myFunction() { return this;}
调用一个函数作为一个全局函数,会导致 this
的值成为全局对象。
作为变量来应用 window
对象很容易使程序解体。
作为办法来调用函数
在 JavaScript
中,您能够把函数定义为对象办法。
上面的例子创立了一个对象(myObject),带有两个属性(firstName 和 lastName),以及一个办法(fullName):
示例
var myObject = { firstName:"Bill", lastName: "Gates", fullName: function () { return this.firstName + " " + this.lastName; }}myObject.fullName(); // 将返回 "Bill Gates"
fullName
办法是一个函数。该函数属于对象。myObject
是函数的拥有者。
被称为 this
的事物,是“领有”这段 JavaScript 代码的对象。在此例中,this
的值是 myObject
。
测试一下!批改这个 fullName
办法来返回 this
的值:
示例
var myObject = { firstName:"Bill", lastName: "Gates", fullName: function () { return this; }}myObject.fullName(); // 将返回 [object Object](拥有者对象)
以对象办法来调用函数, this
的值指向对象自身。
通过结构器来调用函数
如果函数调用的后面是 new
关键字,那么这是一个结构函数调用。
它看起来像你创立一个新的函数,但因为 JavaScript
函数是对象,你实际上创立一个新对象:
示例
// 这是函数结构器:function myFunction(arg1, arg2) { this.firstName = arg1; this.lastName = arg2;}// 创立了一个新对象:var x = new myFunction("Bill", "Gates");x.firstName; // 会返回 "Bill"
结构器调用会创立新对象。新对象会从其结构器继承属性和办法。
结构器内的 this
会指向调用函数时创立的新对象。
setTimeout
(1)ES5
《javascript高级程序设计》中说:“超时调用的代码都是在全局作用域中执行的,因而函数中的this的值在非严格模式下指向window对象,在严格模式下是undefined”。这里探讨的是非严格模式。
es5
中setTimeout
的提早执行函数中的this,永远指向window
。
举例来说:
function myFunction(){ var id=1024; console.log('myFunction中的this:', this, this.id) setTimeout(function(){ // 这里须要留神id和this.id是不一样的 this=window console.log('setTimeout中的this:', this, this.id, id) },100)}var myobj={ id:9528}var id=9527;myFunction(myobj)myFunction.call({id:1987})
输入后果:
myFunction(myobj)
执行后果
myFunction中的this: Window 9527
setTimeout中的this: Window 9527 1024
myFunction.call({id:1987})
执行后果
myFunction中的this: Object { id: 1987 } 1987
setTimeout中的this: Window 9527 1024
补充阐明
一般而言this
总是指向调用该办法的对象,然而应用call()
和apply()
办法时,就会扭转this
的指向,this
的指向会产生转移。
call.(object, arg1, arg2 ...)
apply()
和call()
差不多,只不过apply
第二个参数必须传入的是一个数组,而call
第二个参数能够是任意类型。
obj1.methodName.call(obj2, argument1, argument2)
如上,call
的作用就是把obj1
的办法放到obj2
上应用,js中所有皆对象, 函数是对象, 函数也能够调用办法,前面的argument1..
这些做为参数传入。
A.call( B, x, y )
:就是把A的函数放到B中运行,x 和 y 是A办法的参数。
用call
来实现继承,用this
能够继承myfunc1中的所有办法和属性。
(2)ES6
在ES6
中,setTimeout
外面,如果执行了一个箭头函数,那么这个函数的this
指向的是外层调用者。
function myFunction(){ var id=1024; console.log('myFunction中的this:', this, this.id) setTimeout(()=>{ // 这里须要留神id和this.id是不一样的 this=myFunction的调用者 console.log('setTimeout中的this:', this, this.id, id) },100)}var myobj={ id:9528}var id=9527;myFunction(myobj)myFunction.call({id:1987})
输入后果:
myFunction(myobj)
执行后果
myFunction中的this: Window 9527
setTimeout中的this: Window 9527 1024
myFunction.call({id:1987})
执行后果
myFunction中的this: Object { id: 1987 } 1987
setTimeout中的this: Object { id: 1987 } 1987 1024
ES6
中箭头函数this
会作为变量始终向下级词法作用域查找,直至找到为止。于是这里箭头函数外面的this
,向上找就是myFunction
函数的this
,在这里就是{id:1987}
这个对象。
上面是 Babel 转箭头函数产生的 ES5 代码,就能分明地阐明this
的指向。
// ES6function foo() { setTimeout(() => { console.log('id:', this.id); }, 100);}// ES5function foo() { var _this = this; setTimeout(function () { console.log('id:', _this.id); }, 100);}
下面代码中,转换后的 ES5 版本分明地阐明了,箭头函数外面基本没有本人的this
,而是援用外层的this
。
除了this
,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments
、super
、new.target
。
参考
https://www.w3school.com.cn/js/js_function_call.asp JavaScript 函数 Call
https://es6.ruanyifeng.com/?search=this&x=0&y=0#docs/function#%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E7%82%B9