谈this第二篇

非原创:

想要确定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更加实际。

你可能感兴趣的:(谈this第二篇)