js函数中的this

274 阅读3分钟

  • 函数的分类

怎么定义一个函数:

  • 具名函数

function f1(参数){  //也叫声明式写法
  return 返回值
}

  • 匿名函数
    具名函数去点函数名就是匿名函数

let a =function(参数){ //也叫赋值式写法
   return 返回值
}

  • 构造函数

let f = new Function(x,y,return x+y)

  • 箭头函数

JavaScript在ES6语法中新增了箭头函数,相较于传统函数,箭头函数不仅更加简洁,而且在this方面进行了改进。

let f =()=>{     }

注意:

  1. 函数体只有一句话,可以不加花括号
  2. 函数体没有括号,可以不写return,箭头函数会帮你return
  3. 函数体的花括号与return同在
  4. 直接返回对象会出错,需要加个圆括号

  • 理解常规函数中的this

除了箭头函数,我们使用call方法调用函数时传递的第一个参数,它可以在函数调用时修改,在函数没有调用的时候,this的值是无法确定。

如果没有使用过call方法来调用函数的话,上面的对于this的定义可能不太明白。那么我们需要先理解JS(ES5)里面有三种函数调用形式:

function(p1, p2) 
obj.child.method(p1, p2)
func.call(context, p1, p2) 

其他两种都是语法糖,可以等价的变为call形式:

func(p1, p2) 等价于
func.call(undefined, p1, p2)

obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)

我们把前两种变为第三种(我们称为转换代码),这样的话this就好理解了。

this就是上面代码中的context。也是call传的第一个参数。

我们先看function(p1,p2)中的this如何确定:

function f(){
  console.log(this)
}

f()
//等价于
function f(){
  console.log(this)
}

f.call(undefined)//可以简写为f.call()
//window

注意:

上面打印的this按理应该是undefined,但是浏览器有一条规则:如果你传的context是null或undefined,那么window对象就是默认的context,因此上面打印的结果是window。

如果你希望这里的this不是window,很简单f.call(obj)就可以了。

再看 obj.child.method(p1, p2) 的 this 如何确定

var obj = {
  foo: function(){
    console.log(this)
  }
}

obj.foo() 
//等价于
obj.foo.call(obj)

很显然obj就是this。

[ ] 语法

function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?

我们可以把 arr[0]( ) 想象为arr.0( ),虽然后者的语法错了,但是形式与转换代码里的 obj.child.method(p1, p2) 对应上了,于是就可以愉快的转换了:

      arr[0]() 
假想为    arr.0()
然后转换为 arr.0.call(arr)
那么里面的 this 就是 arr 了 

  • 构造函数中的this

构造函数里的this稍微有点特殊,每个构造函数在new之后都会返回一个对象,这个对象就是this,也就是context上下文。

function Person() {
    this.name = 'Tom'
}
let p = new Person()
console.log(typeof p)  //object
console.log(p.name)    // Tom

  • 箭头函数中的this

箭头函数不接受call传的this,箭头函数没有绑定this,它的this取决于该函数外部非箭头函数的this 值。如果外部没有非箭头函数或者函数没有明确的this值,那么this就是window。

举个栗子:

function foo() {
    return function () {
        // 用的是这一层的this,如果是多层箭头函数,就是最外层的this
        return () => {
            console.log('id:' + this.id)
        }
    }
}
foo().call({id: 1})() // 输出id:1
foo.call({id: 1})()() // 输出id:undefined

foo().call({id: 1})() 执行后返回第二层函数,此时箭头函数的this就是这个函数的this,然后call传了id:1作为this,所以第一次输出1

foo.call({id: 1})()() 这个call传的this是最外层的函数的this,第二层 的this为undfined,所以输出id:undefined。




参考:this 的值到底是什么?一次说清楚



错误请留言指正,谢谢!!!