this和箭头函数

108 阅读4分钟

this的绑定规则

函数中的this指向

<script>
    //定义一个函数
    function foo() {
        consolo.log(this);
    }
    //调用方式一:直接调用
    foo(); //此时this指向window
    
    //调用方式二:将foo放到一个对象中再调用
    var obj = {
        name:"why",
        foo:foo
    }
    obj.foo() // 此时this指向的是obj对象
  1. 函数在调用时,JavaScript会默认给this绑定一个值;
  2. this的绑定和定义的位置(编写的位置)没有关系
  3. this的绑定和调用方式以及调用的位置有关系;
  4. this在运行的时被绑定

this的绑定规则

默认绑定

独立函数调用:没有绑定在任何对象上

//1、普通的函数被独立调用
 function foo() {
        consolo.log(this);
    }
    //调用方式一:直接调用
    foo(); //此时this指向window
    
//2、函数定义在对象中,但是独立调用
var obj = {
    name:'why',
    bar:function(){
        console.log('bar:',this)
    }
 }
 var baz = obj.bar
 baz() //此时this依旧指向window
 
 //3、严格模式下,独立调用的函数中的this指向的是undefined
 // 'use strict'

隐式绑定

function foo() {
    console.log("foo函数:", this)  
}

var obj = {
    bar:foo
}

obj.bar()

new绑定

/* new的执行过程
1、创建新的空对象;
2、将this指向这个空对象;
3、执行函数体中的代码;*/
function foo() {
    console.log("foo函数:", this)  
}
new foo()

显示绑定

var obj = {
    name:"why"
}
function foo() {
    console.log("foo函数:",this)
}

// 执行函数,并且强制this就是obj对象
foo.call()

apply/call/bind

function foo(name, age, height) {
    console.log("foo函数:",this)
}
//apply 
//第一个参数:绑定this
//第二个参数:传入额外的实参,以数组的形式
func.apply(thisArg,[argsArray])
foo.apply('apply',['catherine',20,1.66])

//call
//第一个参数:绑定this
//参数列表:后续的参数以多参数的形式传递,会作为实参
function.call(thisArg,arg1,arg2,...)
foo.call('call','james',25,2.05)

//bind
//
function foo(name, age, height) {
    console.log("foo函数:",this)
}
var obj = {name:"Jack"}
//1.bind函数的基本使用
var bar = foo.bind(obj)

内置函数的调用绑定

内置函数(第三方库):无法明确知道,根据经验

//1、定时器
setTimeout(function() {
    console.log('定时器函数:',this)
},1000)

//2、按钮的点击监听
var btn = document.querySelector('button')
btn.onclick = function() {
    console.log("btn的点击:",this)
}

btn.addEventListener("click",function(){
    console.log("btn的点击:",this)
})

this绑定的优先级

1、默认规则的优先级最低
2、显示绑定的优先级高于隐式绑定
3、new不可以和apply/call一起使用,new绑定也高于隐式函数
4、new绑定的优先级高于bind
5、bind的优先级高于apply/call

function foo() {
    console.log("foo函数:",this)
}
var obj = {foo:foo}
obj.foo.apply("123")//此时this指向"123",apply为显示绑定优先级更高

this绑定之外的情况

1、显示绑定中,我们传入一个null/undefined,那么显示绑定会被忽略,执行默认绑定

function foo() {
    console.log("foo:",this)
}
foo.apply('abc')
foo.apply(null) //this指向Windows,严格模式下指向null
foo.apply(undefined)//this指向Windows,严格模式下指向undefined

箭头函数(es6)

1、箭头函数不能绑定this、arguments;
2、箭头函数不能作为构造函数来使用(不能和new一起使用)

// Function expression
const calcAge2 = function (birthYear) {
    return 2037 - birthYear;
}

// Arrow function
//没有参数
const foo = () => {}

// 只有一个参数
const calcAge3 = birthYear => 2037 - birthYear;
//use
const age3 = calcAge3(1996);


// 函数中超过一个表达式时:
const yearUntilRetirement = birthYear => {
    const age = 2037 - birthYear;
    const retirement = 65 - age;
    return retirement
}

// 函数中有两个参数时:
const yearUntilRetirement = (birthYear,firstName) => {
    const age = 2037 - birthYear;
    const retirement = 65 - age;
    return '${firstName} retires in '${retirement}' years.'
}

//如果箭头函数默认返回值是一个对象,那么这个对象必须加()
var arrFn = () => ({name:"TOM"})

//箭头函数实现nums的所有偶数平方的和
var nums = [20,30,11,15,111]
var result = nums.filter(item => item % 2 === 0)
                 .map(item => item * item)
                 .reduce((prevValue,item) => prevValue + item)

箭头函数中的this使用

  • 箭头函数中的 this 是在箭头函数定义时就决定的,而且不可修改(call, apply, bind)
  • 默认指向定义它时,所处上下文的对象的this指向。即ES6箭头函数里this的指向就是上下文里对象this指向,偶尔没有上下文对象,this就指向window

相关文章:juejin.cn/post/684490…

面试题练习

var name = "window";

var person = {
    name: "person",
    sayName: function () {
        console.log(this.name);
    }
};

function sayName() {
    var sss = person.sayName;
    sss();// 独立函数调用,使用默认绑定,指定window -> window
    person.sayName(); // 隐式绑定,this指向person对象 -> person
    (person.sayName)(); // 与上一行完全一样:隐式绑定,this指向person对象 -> person
    (b = person.sayName)(); // 间接函数引用,this指向window
}

sayName();
var name = "window"

var person1 = {
    name: "person1",
    foo1: function () {
        console.log(this.name)
    },
    foo2: () => console.log(this.name),
    foo3: function(){
        return function() {
            console.log(this.name)
        }
    },
    foo4: function () {
        
        return () => {
            console.log(this.name)
        }
    } 
}
var person2 = {name : 'person2')

person1.foo1(); //隐式绑定:person1
person1.foo1.call(person2);//person2

person1.foo2(); // 箭头函数去上层作用域找,window
person1.foo2.call(person2); // call无法绑定箭头函数,还是去上层作用域找,window

person1.foo3()(); // 默认绑定:window
person1.foo3.call(person2)(); //默认绑定 :window
person1.foo3().call(person2); // 显示绑定:person2

person1.foo4()(); // person1
person1.foo4.call(person2)(); // person2
person1.foo4().call(person2); // person1