this
的五种不同情形
默认情况
默认情况下,纯粹函数调用时,因为没有调用该方法的对象,故而此时的this
是undefined
,JavaScript解释器会自动把这个对象指向全局对象Global,在浏览器环境下,也即window对象。
window.x = 'Jackie' |
阮一峰老师的博客中提到:
在严格模式(
"use strict"
)下,会禁止this
指向全局对象,此时的this
会是undefined
。
事实上,ES5的规范 中修改了描述,仅当非严格模式下才会有 this
指向的转变。所以此时this
无法改变指向,就会是undefined
,但并不是说无法指向全局对象。
; |
作为对象的方法调用
此时this
指向调用这个方法的对象。
var x = 'Property of Window' |
call
、apply
和bind
的显式绑定
call
、apply
和bind
都可以改变一个函数的this
指向。
call
和apply
call
和apply
会将它们的调用对象的this
指向它们的第一个参数。
function f () { |
当传入的第一个参数为undefined,或者不传入参数时,在非严格模式下,自动会将this
指向全局对象Global,在浏览器里是window
对象,严格模式下则会是undefined
:
function f () { |
call
和apply
没有本质区别。唯一的区别在于:
call()
方法接受的是若干个参数的列表,而apply()
方法接受的是一个包含多个参数的数组。
bind
bind
和前面两者也并未有什么本质的区别,只不过bind
将第一个参数绑定当调用函数的this
上,并将这个函数返回(不执行)。
function f () { |
构造函数
当一个函数被当做构造函数,用new
关键字新建一个对象的时候,这个函数内部的this
以及原型链上的this
都会指向这个新建的对象。
function Jackie(para) { |
其他值得注意的绑定
放在超时代码里
JavaScript中超时调用的代码,函数中this的值会指向window对象,在严格模式下也一样。因为超时调用的代码都会有一个隐式绑定:setTimeout(f, time) == setTimeout(f.bind(window), time)
。"use stric"
var x = 'Property of Window'
var obj = {}
obj.x = 'Property of obj'
obj.ff = function () {
setTimeout(
function () {
console.log(this.x)
}, 100)
}
obj.ff() // Property of Window
// 可以这么解决问题
obj.fff = function () {
var that = this
setTimeout(
function () {
console.log(that.x)
}, 100)
}
obj.fff() // Property of obj
事件监听函数中的this
事件监听函数中的this
指向监听对象。
var one = document.getElementById('one') |
箭头函数
箭头函数中this
的指向,在函数定义时即绑定完毕,且后续无法更改。(即,会跟它的上级作用域的this
指针保持一致)
var obj = { |
一个更神奇的例子,超时调用的代码在定义时,绑定了this
的指向。
function foo() { |
绑定的优先级
var obj = {x: 0, name: 'obj'} |
可以见得,优先级从高到低:
new
,构造绑定bind
,显式绑定call
/apply
,显示绑定- 作为方法绑定
- 默认绑定