【JavaScript】来自 ES6 的嘲讽:箭头函数与 this

提起 ES6 的箭头函数,就不得不提提 this。

自 ES3, JavaScript 便支持 this,那 this 到底是什么呢?

我们在控制台试图打出 this:

this  //Window
this === window //true
 
let x = function() {
  console.log(this)  
}
x() //Window
let name = "windowName"
let block = {
    name: "block",
    fn : function () {
        console.log(this.name)     
    }
}
block.fn() //block

用面向对象的逻辑来理解,this 应当是对象本身,与其类似,在这里的 this 看起来是函数调用者本身。

x() 其实为 window.x(), 故其 this 应当为 window,block.fn()中函数 ‘fn()’ 中的 this 应当为 block 本身。

 

再看一个有趣的例子:

let name = "windowName"
let block = {
    name: "block",
    fn : function () {
        console.log(this.name)    
    }
}
 
let b = block.fn
b()  //windowName

按照上述逻辑,this 为函数调用者本身,在这个例子里,把 block.fn 赋值给 b,再调用 b(),那么 b() 的函数调用者是 window 啊,故打印出 windowName 没问题啊,多好的一个 this,代表函数调用者本身。

let name = 'windowName'
let block = {
    name: 'block',
    fn : function () {
       setTimeout( function() {
         console.log(this)
         console.log(this.name)
       }, 500) 
    }
}
block.fn()  //Window  //windowName

而上述代码中,我们发现定时器中的函数调用者竟然是 window,而非 block,那我们要想在定时器的函数中打印出 block 只能曲线救国——转移 this:

let name = 'windowName'
let block = {
    name: 'block',
    fn : function () {
       let that = this
       setTimeout( function() {
         console.log(that.name)
       }, 500) 
    }
}
block.fn()  //block

虽然麻烦点,不过还好,算是严谨的 this,可坏就坏在,其实 this 本身可以被人为改变。

let name = 'windowName'
let block = {
    name: 'block',
    fn : function () {
       setTimeout( function() {
         console.log(this.name)
       }.call(block), 500) 
    }
}
block.fn()  //block

什么,那个让我们觉得神圣不可侵犯而又严谨的 this 变了?!

是的,变了,它变了,而这会有什么影响呢?

让我们试想一下,当我们调用一个 API 的函数时,我们不确定其 this 是否为函数调用者本身,这是一件多么糟糕的事情。

那么到底 this 是什么呢?

 

一句话来概括:this 是 call 的第一个参数。如下;

let name = 'windowName'
let block = {
    name: 'block',
    fn : function () {
         console.log(this.name)
    }
}
block.fn() //block
block.fn.call(window)  //windowName

 

继而,this 也是 bind、apply 的第一个参数。

至此我们搞懂什么是 this 了;

而至于为什么说箭头函数是对 JavaScript 的嘲讽,原因有二:

其一为当意图传递的 this 为外部的 this 但却非函数调用者时,我们需要花费的成本太高,例如使用 that 传递,例如使用 bind修改;

其二为当函数不需要 this 的时候,具名函数或匿名函数的声明太繁琐。

 

let name = 'windowName'
let block = {
    name: 'block',
    fn : function () {
       setTimeout( () => {
         console.log(this.name)
       }, 500) 
    }
}
block.fn()  //block

是的,不需要 bind 也不需要 使用 that,只需要简化声明函数的方式,就可以实现在定时器中使用外部 this。

 

箭头函数还有简化函数声明的优点,例如我们实现数组的次方的次方计算。

[1,2,3,4].map(array => array * array).map(array => array * array) //[1, 16, 81, 256]

而改用声明匿名函数的方法呢?

[1,2,3,4].map(function(array) {
  return array * array
}).map(function(array) {
  return array * array
})  //[1, 16, 81, 256]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值