常规函数和箭头函数的this绑定问题

核心要点

function(){} 和 () => {} 的最大区别在于前者会在运行时绑定this对象,后者不会

由于function(){}在运行时在内部自动绑定this对象,则不会访问外部作用域this
由于() => {}不能自动绑定this对象,则只能访问外部作用域this

如果要使用动态绑定的this,则使用function(){}
如果要使用外部作用域的this,则使用() => {}

估计ES6就是因为function(){}总是自动绑定this造成嵌套function时需要let self = this,然后需要在内层function使用self.xxx调用外层this,才新添加了一个不会自动绑定this的函数:箭头函数 () => {}

function(){}的this绑定规则

function(){}在运行时(被调用的时候)会基于绑定规则动态进行this绑定

有两点强调:

  • this是在运行时绑定的,不是定义时
  • 要看this的指向,关键在于看函数调用的位置和方式

根据函数调用位置和方式不同,有四种绑定策略

1.默认绑定
如果直接调用函数,则将this绑定到全局对象,在Node中是global,在浏览器中是window

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

// 运行时绑定
foo()

2.隐式绑定
如果有上下文对象调用函数,则将this绑定到上下文对象

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

// 运行时绑定
obj.foo()

3.显式绑定
通过调用函数的call,apply,bind方法进行绑定

function foo () {
    console.log(this);
}
const obj = { a: 1 }

// 运行时绑定
foo.call(obj)
foo.apply(obj)
foo.bind(obj)()

4.new绑定
new的过程也叫函数的“构造调用”,经历了以下几个步骤:
1. 创建一个空对象obj
2. 将对象obj的Prototype关联到构造函数的Prototype
3. 将对象绑定到构造函数的this
4. 如果构造函数没有返回对象,则返回对象obj

function Foo () {
    console.log(this);
}

// 运行时绑定
foo = new Foo()

常见场景归纳

1.对象方法定义:使用function(){} 以获得this绑定
2.回调函数场景:使用() => {} 以访问外部作用域this

const dog = {
    name: "旺仔",
    eat: function (callback) {
        // 这里的this采用隐式绑定策略
        // 因为调用方式是this.eat() (run和sleep方法中)
        setTimeout(() => {
            console.log(`${this.name}吃饱了`)
            callback()
        }, 3000);
    },
    run: function () {
        // 这里的this无法进行绑定,只能从外层作用域获得,在这里指向最外层(模块级别)this
        // 在node中模块级别this指向module.exports
        // node是模块化的,模块本身存在独立作用域,要和浏览器的全局概念区分
        this.eat(() => {
            console.log(`${this.name}开始跑步`);
        })
    },
    sleep: function () {
        // 这里的this采用默认绑定策略
        // 因为调用方式是callback() (eat方法中)
        this.eat(function () {
            console.log(`${this.name}准备睡觉`);
        })
    }
}

dog.run()
// 旺仔吃饱了
// 旺仔开始跑步
dog.sleep()
// 旺仔吃饱了
// undefined准备睡觉

3.事件监听场景:使用function(){} 以获得this绑定

// 事件监听器调用仍然是上下文调用,socket.handle()
socket.on('data', function handle () {
    console.log(this)
})

原文地址:https://www.cnblogs.com/Peter2014/p/12168456.html

时间: 2024-08-30 13:35:37

常规函数和箭头函数的this绑定问题的相关文章

论普通函数和箭头函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱.就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和箭头函数的区别: 箭头函数的this指向规则: 1. 箭头函数没有prototype(原型),所以箭头函数本身没有this let a = () =>{}; console.log(a.prototype); // undefined 2. 箭头函数的this指向在定义的时候继承自外层第一个普通函数的this

e_函数_箭头函数

函数 箭头函数 // 有有一个变量且直接return的 var f = v => v; // 等同于 var f = function (v) { return v; }; // 不需要参数或需要多个参数 不直接return的 var sum = (num1, num2) => { let k=num1 + num2; return k; }; // 等同于 var sum = function(num1, num2) { let k=num1 + num2; return k; }; 箭头函

6 JavaScript函数&内置构造&函数提升&函数对象&箭头函数&函数参数&参数的值传递与对象传递

JavaScript函数:使用关键字function定义,也可以使用内置的JavaScript函数构造器定义 匿名函数: 函数表达式可以存储在变量中,并且该变量也可以作为函数使用. 实际上是匿名函数. <body> <p>函数存储在变量后,变量可作为函数使用:</p> <p id="demo"></p> <script> var x = function(a,b){return a+b; }; document.g

JS函数和箭头函数

函数的声明和调用 函数定义可以使用"function"关键字,代码函数头和函数体组成,函数头可以由函数名和参数列表组成,语法格式:函数名(参数列表){函数体}.如 function name(arg){console.log(arg)} 调用 name(arg) 当函数没有函数名的时候称匿名函数 function(arg){console.log(arg)} 通常需要赋值给一个变量,不然报错 var name=function(arg) { console.log(arg) } 调用

区别ES3ES5和ES6this的指向问题。区分普通函数和箭头函数中this的指向问题

ES3 ES5this的指向问题 this指的是该函数被调用的对象 var foo = function () { this.a = 'a', this.b = 'b', this.c = { a: 'new a', b: function () { //new a 此时this指的是该函数被调用的对象 return this.a; } } } console.log(new foo().c.b()); //new a ES6的箭头函数 箭头函数的this指的是定义时this的指向,b在定义时,

ES6深入浅出-2 新版函数:箭头函数 2 视频-2.视频 箭头函数杂谈

杂谈coffeescript 箭头函数抄的是谁? coffeescript 双箭头的形式 箭头函数简洁的语法 数组内每一个值都平方一下 Map的写法 箭头函数的写法 平方后,每一个值再加1 number变量改成用n,更简化 瘦箭头 瘦箭头其实就是function 判断response里面的对象是否存在的情况 coffescript里面的解决方法,直接用问号解决了. vue中说不要使用箭头函数? 因为vue中依赖this 用到了箭头函数就别用this function()简写的写法,onClick

ES6深入浅出-2 新版函数:箭头函数 2 视频-1.视频 箭头函数

ES3里面的写法 匿名函数是用不了的 还是需要给他赋值 选中的这一部分叫做匿名函数 等于号叫做赋值 let xxx叫做声明 所以说这个地方是三个语法,首先声明一个匿名函数,然后声明一个xxx变量,最后把这个匿名函数赋值给这个变量xxx es6箭头函数 箭头函数只能做赋值,不能做声明 这是一个标准的箭头函数 写法2,只有一个参数 如果只有一个函数,可以不用写括号 调用一下做测试 写法3,函数体只有一句话的情况 如果函数体只有一句话,那么是可以不写花括号的. 假设我们的函数体只有return p1+

ES6 function函数和箭头函数区别

1.写法不一样 //function function fn(a,b){ return a+b } //arrow function var foo = (a,b)=>{ return a+b } 2.this的指向,function中的this可变(window,内部),箭头函数固定不变指向window function foo(){ console.log(this) } var obj = {aa:foo} foo() //window obj.aa()//obj var foo = ()

重学ES6(三):函数和箭头函数

函数的参数默认值 ES5---参数的默认值通常都是写在函数体中,不传参即用默认参数 // ES5 // 设置参数默认值,未传入参数时按照默认值 function f(x, y, z) { if (y === undefined) { y = 7 } if (z === undefined) { z = 42 } return x + y + z } console.log(f(1)) // 50 console.log(f(1, 8, 43)) // 52 原文地址:https://www.cn