非原创:
想要确定this的指向,需要分下列几种情况进行讨论:
全局代码中的this
函数中的this
其中函数中的this比较复杂,也更为常见,下面会着重说明。
全局代码中的 THIS
这个很好理解,就是指向全局对象window,如果是严格模式则是undefined,下面为了简便,直接用global代替,不再对是否是严格模式进行区分。
this.a = 10
console.log(a) // 10
b = 20
console.log(this.b) // 20
var c = 30
console.log(this.c) // 30
函数中的 THIS
先上结论:
函数上下文中的this值由调用者提供,并由表达式的形式确定;
如果在调用括号的左侧存在引用类型的值,则将this设置为该引用类型的base对象;
在所有其他情况下,this的值始终设置为null,因为null没有意义,所以被隐式转换为全局对象。
结论中的细节下面将会介绍。
引用类型
为了理解方便,先介绍一个基本概念:
引用类型可以表示为对象,base是属性所属的对象,propertyName是此对象中属性的名字,strict表示是否为严格模式。
var foo = 10
function bar() {}
可以理解成:
var fooReference = {
base: global,
propertyName: 'foo'
}
var barReference = {
base: global,
propertyName: 'bar'
}
OK,那么下面再来两个 融会贯通一下。
function foo() {
console.log(this)
}
foo() // global
var fooReference = {
base: global,
propertyName: 'foo'
}
结论很显然,括号左边是foo函数,即window.foo(),引用类型,那么this指向base,即global。
扩展一下:
foo.prototype.constructor() // foo.prototype
var fooPrototypeConstructorReference = {
base: foo.prototype,
property�Name: 'constructor'
}
同样的判断方法~
再来一个 :
function foo() {
console.log(this.bar)
}
var x = { bar: 10 }
var y = { bar: 20 }
x.test = foo
y.test = foo
x.test() // 10
y.test() // 20
var xTestReference = {
base: x,
propertyName: 'test'
}
// y应该不用再写了吧
非引用类型
非引用类型就一句话:全局对象。
老规矩,举 :
(function() {
console.log(this) // null => global
})()
// 括号内�为函数声明,并非引用
下面的 可能会让人困惑:
var foo = {
bar: function() {
console.log(this)
}
}
foo.bar() // Reference, OK => foo
(foo.bar)() // Reference, OK => foo
(foo.bar = foo.bar)() // global
(false || foo.bar)() // global
(foo.bar, foo.bar)() // global
后三组由于进行�了赋值和运算,因此base丢失,他们其实都变成了函数声明,因此类似于自执行函数,this指向global。
另外两种情况
还有两种情况,如果作为构造函数被调用,指向实例化对象;如果是call和apply调用,指向�他们的参数。
一点想法
this的指向确实是个比较�麻烦的点,理解上不困难,但是有些点需要记忆,我觉得比较合适的方式是,在用到过程中学习this,比如react中为什么要在constructor中�bind(this),为什么Vue的组件中,data中的数据要写在return中,通过这种方式具体的学习�this更加实际。