箭头函数与普通函数的this指向比较

这边文章的箭头函数与普通函数的this指向没总结好 见下一篇

    let v = v => v

      // 等同于
      let f = function (f) {
         return f
      }
console.log(v(5));  //5

2.如果箭头函数的代码块部分 多于一条语句 ,就要使用 大括号 将它们括起来,并且使用 return 语句返回。

	     
   let sum = (num1, num2) => { 
         console.log(12);
         return num1 + num2 }

console.log(sum(5,10));

3.由于大括号被解释为代码块(代码块就是整个{}+包裹的内容),所以如果箭头函数 直接返回一个对象 ,必须 在对象外面加上括号 ,否则会报错

let getTempItem = id => ({ id: id, name: 'Temp' })
console.log(getTempItem(1));

4.下面是一种特殊情况,虽然可以运行,但会得到错误的结果。

	let foo = () => { a: 1 } // undefined

代码中,原始意图是返回一个对象{ a: 1 },但是由于引擎认为大括号是代码块,所以执行了一行语句a: 1。这时,a可以被解释为语句的标签,因此实际执行的语句是1;,然后函数就结束了,没有返回值。

5.箭头函数可以与变量解构结合使用

let person={
    fist:"shi",
    last:"li"
}
const full = ({fist, last}) => fist + ' ' + last

console.log(full(person));


    //等同于
    function full(person){
        return person.first + ' ' + person.last
    }

6.箭头函数使得表达更加简洁

const isEven = n => n % 2 === 0
console.log(isEven(4));  //true

7.如果箭头函数 不需要参数 或 需要多个参数 ,就使用一个 圆括号 代表参数部分,需要一个参数用不用圆括号都行

注:箭头函数根本没有自己区域的this对象,实际是用的外层代码块(函数内)的 this 对象。

	function Timer(){
        this.s1 = 0
        this.s2 = 0
        // 箭头函数
        setInterval(() => 
       { this.s1++,
        console.log(this)//Timer {s1: 3, s2: 0} 
        }
        1000)
        // 普通函数
        setInterval(function (){
            this.s2++
            console.log(this)//windows
        }, 1000)
    }
    var timer = new Timer()

    setTimeout(() => console.log('s1: ', timer.s1),3100) //s1:  3
    setTimeout(() => console.log('s2: ', timer.s2),3100) //s2:  0

上面代码中,Timer 函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的 this 绑定定义时所在的作用域(即 Timer 函数)(其实这个this就是函数代码块的this对象),后者的 this 指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1 被更新了 3 次,而 timer.s2 一次都没更新。

//更好的说明箭头函数和普通函数。前者的 this 绑定定义时所在的作用域(即 Timer 函数),后者的 this 指向运行时所在的作用域(即全局对象)
console.log(this);  //[object Window]

var s2=0
function Timer(){
        this.s1 = 0
        //两个定时器不属于构造函数模板里,因为this.才属于构造函数的属性和方法
        //两个定时器只是用来演示箭头函数与普通函数的this指向问题
        // 箭头函数   // this指向上下文函数的this指向
        setInterval(() => this.s1++, 1000)
        // 普通函数
        setInterval(function (){
            this.s2++    //this指向全局作用域  没人调用默认全局
        }, 1000)
    }
     var timer = new Timer()  //构造函数new时即调用会返回一个新对象,同时定时器会自调用执行

     setTimeout(() => console.log('s1: ', timer.s1),3100) //s1:  3
    setTimeout(() => console.log('s2: ', s2),3100) //s2:  3
var定义的变量是全局变量或者函数变量
let定义的变量是块级的变量,只在{}区域内有效 
虽然this指向全局作用域,但let只在它的块级作用域内有效
  let num = 100; // let 声明的是块级变量,不是全局变量
    let fun = ()=>{
        console.log("箭头函数let num:"+this.num);  //undefined
    }
fun()

      var t=3
 function name(params) {
      var t=2
     console.log(this.t); //3  //this直接指向的就是全局作用域,不会像变量提升那样一层一层的向上找
 }
name() 

下面这个例子能很好的说明箭头函数根本没有自己 区域的this,用的 this 实际是外层代码块(函数内)的 this 。

  let handler = {
        id: '12345',

        init: function() {
            console.log(555);
            document.addEventListener('click',
              
                function (event) {
                  console.log(this);  // document文档  //匿名函数没人调用
                    this.doSomething(event.type)
                } ,false
                
                )
        },
            
        doSomething: function(type) {
            console.log(78878);
            console.log('Handling ' + type + 'for ' + this.id)
        }
    }
    handler.init()  //this.doSomething is not a function
 let handler = {
        id: '12345',

        init: function() {
            document.addEventListener('click',
                event => {
                    console.log(this);  //{id: '12345', init: ƒ, doSomething: ƒ}   //this指向上下文函数的this指向
                    this.doSomething(event.type)
                },false
               
                )
        },
            
        doSomething: function(type) {
            console.log(78878);
            console.log('Handling ' + type + 'for ' + this.id)
        }
    }
    handler.init() //Handling clickfor 12345

上面代码的 init() 方法中,使用了箭头函数,这导致这个箭头函数里面的this ,总是指向 handler 对象。如果回调函数是普通函数,那么运行this.doSomething() 这一行会报错,因为此时 this 指向 document 对象。

小编跟我说了半天 最后跟我说箭头函数里没this
我自己的代码

	let handler = {
        id: '12345',
        init: function() {
            console.log(this);  // {id: '12345', init: ƒ}
        },   
    }
    handler.init() 

箭头函数里确实没this,这个this就是外层代码块的 this对象而已

不适用场合
1.定义对象的方法,且该方法内部包括this。


    const cat = {
        lives: 9,
        jumps: () => {
            console.log(this);  //windows
            this.lives--
        }
    }
    cat.jumps() 
    
const cat = {
        lives: 9,
        jumps: function () {
            console.log(this);  //{lives: 9, jumps: ƒ}
            this.lives--
        }
    }
    cat.jumps() 

这是因为对象不构成单独的作用域,导致 jumps 箭头函数定义时的作用域就是全局作用域。

	var s = 21

    const obj = {
        s: 42,
        m: () => console.log(this.s) 
    }

    obj.m() //21

由于上面这个原因,对象的属性方法建议使用function写法定义,不要用箭头函数定义。

	var button = document.getElementById('press');
    button.addEventListener('click', () => {
        this.classList.toggle('on')
    })

上面代码运行时,点击按钮会报错,因为 button 的监听函数是一个箭头函数,导致里面的 this 就是全局对象。如果改成普通函数,this 就会动态指向被点击的按钮对象。

总的来说箭头函数里的this指向有不确定性,主要看你外面的代码块,
两种情况:要是构造函数里的一个普通方法(不是this.的方法)或者定义一个对象里面有传统方法function定义的方法时的话箭头函数的this确实只会指向当前的代码块区域中,而普通函数的this确实会指向全局。

但你不能说箭头函数里的this都是指向{}的代码块中,这种想法是错的,特殊情况:上面列举的不适用场合的三种情况就说明箭头函数this不是都指向{}的代码块中 反而相反了,箭头函数里this指向全局,普通函数里的this指向{}代码块内**

注:箭头函数根本没有自己区域的this对象,实际是用的外层代码块(函数内)的 this 对象。 但是有时候不同的定义形式确实会导致箭头函数和普通函数里的this指向不同

构造函数里的this. 方法里面的this指向无论是箭头函数还是普通函数都会指向代码块 ,不是this.的方法的话箭头函数的this指向当前的代码块内,而普通函数的this指向全局。*

    function Person(name, age) {
	this.name = name;
	this.age = age;
      (()=>{
            console.log(this); //this指向上下文函数的this指向 
        })();

        (function(){
            console.log(this); //匿名函数没人调用,this指向全局作用域
        })()
    
	this.eating = () =>{
        console.log(this);  //已调用 Person {name: 'zs', age: 12, eating: ƒ}
		console.log(this.name + ' is eating');
	}
}

const p1 = new Person('zs', 12);
p1.eating()  //已调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值