this指向 箭头函数中的this call、apply和bind方法的用法以及区别

this 指向

在这里插入图片描述

1.普通函数的this:指向它的调用者,如果没有调用者则默认指向window.
2.箭头函数的this: 指向箭头函数定义时所处的对象,而不是箭头函数使用时所在的对象,默认使用父级的this 箭头函数的父级还箭头还是 就从父级开始 向上查找 直到有(实际上箭头函数里并没有 this,如果你在箭头函数里看到 this,你直接把它当作箭头函数外面的 this 即可。外面的 this 是什么,箭头函数里面的 this 就还是什么,因为箭头函数本身不支持 this。就默认看成使用父级的this)
对象中的函数叫方法
this 是当前对象的引用
如果函数是对象属性 或者类方法 this 就是当前对象
如果只是普通的函数 就是全局的对象 就是window

let obj = {
    name :"ThinkerWing",
    show:function () {
        // console.log(this); // 返回当前对象obj
        // return this.name;
        function render() {
            console.log(this);//Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …} 返回全局的对象
        }
        render();
    }
}
    obj.show();
console.log(this===window); //true
console.log(this===obj)  //false

函数是不属于任何对象的,this是函数运行时再决定的

  function user(name) {     //找到当前的参数  不然name变成window
      this.name = name; //这是属性 下面那条也是 属性的函数为方法
      this.show = function () {
         function render() {
             console.log(this);//返回window
         }
         render()
          console.log(this); //返回user 对象
      }
  }
  let TK = new user("ThinkerWing");
  TK.show();

看看箭头函数的案例

let name = {
    lastname:"wing",
    firstname:["thinker","Thinker"],
    show:function () {
        console.log(this);
        const self = this;
        return this.firstname.map(function (value) {
            return `${self.firstname}-${value}`
            // 由上例子知普通函数就是全局的对象 window 所以这边用常量改变this指针
            //(index) 0 thinker,Thinker -thinker
            //(index) 1  thinker,Thinker -Thinker
        })
    }
};
console.table(name.show());

了解一下箭头函数的this 指向 然后利用箭头函数 重写上一个案例


var str = 'window';
const obj = {
    str:'obj',
    fn: ()=>{
        console.log(this.str);
    },
    fn2: function(){
        console.log(this.str, '当前词法作用域中的this');
        return {
            str: '我是fn2中的Obj 碰不到我的 箭头函数的this是指向上一级的',
            fn: ()=>{
                console.log(this.str);
            }
        }
    }
};

obj.newFn = ()=>{
    console.log(this.str);
};
obj.fn2(); //打印  obj 当前词法作用域中的this
obj.fn();//打印window
obj.newFn(); // 指向上一级的str  打印 window
var newObj = obj.fn2();
newObj.fn();//指向fn2()属性的上一级 即对象obj 打印obj的str即打印obj

了解了箭头函数的指向是父级的作用域 此时就不用担心普通函数的this指向全局

let name = {
    lastname:"wing",
    firstname:["thinker","Thinker"],
    show:function () {
        console.log(this); // 打印name 对象
        return this.firstname.map( (v)=> {
           console.log(this); //  打印值与上方的一样 同为name对象
            //箭头函数指向父级作用域
          return `${this.firstname}-${v}`
          //(index) 0 thinker,Thinker -thinker
            //(index) 1  thinker,Thinker -Thinker
        })
    }
};
console.table(name.show());

call、apply和bind方法的用法以及区别

先介绍一下apply是怎么传数组的 通过一个比大小的案例来解释

let arr = [0,1,2,3,4,5,6,7,8,9];
    console.log(Math.max.apply(Math,arr)); //打印9

其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。
apply是数组

   let TK = {
        name:"ThinkerWing"
    };
    function user(age,sex) {
        console.log(age+"岁的"+sex+":"+this.name);
    }
    user.call(TK,20,"男生"); //打印 20岁的男生:ThinkerWing
    user.apply(TK,[20,"男生"])  //打印 20岁的男生:ThinkerWing

来一个证明他们基本类似

function show() {
    alert(this.innerHTML)
}
let btn = document.querySelectorAll("button");
for (let i = 0 ; i<btn.length;i++){
    btn[i].addEventListener("click",event=>{
      show.apply(event.target) //此处call与apply是一样的
        // console.log(this) // 打印 window 因为这里箭头函数的父级就是window
    })
}

重新回顾一下this的指向 为什么Age能打印20而fun 同样也是this.age却不行呢?
因为Age指向了全局 而fun中的指向了obj对象,对象中无age定义。

    var name = "ThinkerWing", age = 20;
    var obj = {
        name : 'TK',
        Age: console.log(this.age), //打印20
        fun:function () {
            console.log(this.name+"年龄"+this.age);
        }
    };
    obj.fun() //打印 TK年龄undefined
var name = "ThinkerWing", age = 20;
    var obj = {
        name : 'TK',
        Age: console.log(this.age), //打印20
        fun:function (a,b,c) {
            console.log(this.name+"年龄"+this.age+a+b+c);
        }
    };
    var demo = {
        name:'baby',
        age:20
    };
    //缺少三个传参  因为这边只想调用年龄 姓名 证明三个实现是一样的
    obj.fun.call(demo);  //baby年龄20undefinedundefinedundefined
    obj.fun.apply(demo);  //baby年龄20undefinedundefinedundefined
    obj.fun.bind(demo)();  //baby年龄20undefinedundefinedundefined
    obj.fun.call(demo,"相遇","福州",2019); //baby年龄20相遇福州2019
    obj.fun.apply(demo,["相遇","福州",2019]);//baby年龄20相遇福州2019
    obj.fun.bind(demo,"相遇","福州",2019)();//baby年龄20相遇福州2019
    obj.fun.bind(demo,["相遇","福州",2019])();//baby年龄20相遇,福州,2019undefinedundefined
    //以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
    // 由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

All in all (总的来说综上所述):

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:

call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面

apply 的所有参数都必须放在一个数组里面传进去

bind 除了返回是函数以外,它 的参数和 call 一样。

当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

来几个面试题试试

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

    var bar = obj.foo
    obj.foo() 
    bar() 

答案: obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window

因为this就是对当前对象的引用 所以obj.foo() 打印了对象
bar() 是定义对象中的函数 普通的函数就是全局对象

var x = 12;
function test() {
    console.log(this.x);
}

var obj = {
    x:45,
    ss:function () {
        console.log(this.x);
    }
};
var bar = obj.ss;
test(); 
obj.ss();
bar()

答案:
test(); //12
obj.ss(); //45
bar() //12
test 只是普通函数 this指向全局 全局变量 x =12;
这题同上题相似 只是换了数据

var name = "222";
    var a = {
        name :"111",
        say : function () {
            console.log(this.name);
        }
    };
    var fun = a.say;
    fun();   // 答案
    a.say(); //答案
    var b = {
        name : "333",
        say : function (fun) {
            fun()
        }
    };
    b.say(a.say); //答案
    b.say = a.say;
    b.say(); // 答案
	 fun();   //222
     a.say(); //111
     b.say(a.say); //222
     b.say(); // 333

第一问 fun =a.say , 只是一个普通函数 全局变量 222
第二问 a.say() 指向对象 a 的name 111
第三问 先看括号中的a.say 类似将fun=a.say 然后执行fun() fun()的归属是window 不是某个对象中的
第四问 b.say() 指向对象 b 的name 333

发布了5 篇原创文章 · 获赞 12 · 访问量 4911

猜你喜欢

转载自blog.csdn.net/daddykei/article/details/105720061