浅谈js中this指向问题

this指向

默认绑定

函数在调用的时候没有任何前缀,会有默认绑定,默认绑定window对象

 function fn1() {
        let fn2 = function () {
          console.log("fn2",this); //window
          fn3();
        };
        console.log("fn1",this); //window
        fn2();
      }

      function fn3() {
        console.log("fn3",this); //window
      }
      fn1();
    //   fn1-fn2-fn3
 console.log(this === window); // true
      this.a = 100;
      console.log(window.a); // 100
      console.log(a); //100
      var b = 200;
      console.log(window.b); //200
      let c = 300;
      console.log(window.c); // undefined ,let不是全局的

隐式绑定

如果函数在调用的时候,前面存在一个调用对象,那么this就会绑定在他身上 谁调用指向谁

此处的this指向obj

 function fun1() {
        console.log(this); // obj
      }
      let obj = {
        name: "青龙白虎",
        func: fun1,
      };
      obj.func();
 let name = "zs";
      let obj = {
        name: "pyy",
        age: 17,
        say: function () {
          return `我叫${this.name}我今年${this.age}`;
        },
      };
      let say = obj.say;
    //   注意:
      // this关键字是在函数调用时才做绑定的,
    //   say()前面是什么?什么都没有,因此this关键词就将指向全局window。
    //   console.log(say());  //我叫我今年undefined岁
  
    //  正确
    // console.log(obj.say()) //我叫pyy我今年17岁

如果是前面有多个对象,this指向最近的对象

  function fun1() {
        console.log(this.name); // 青龙白虎
      }
      let obj = {
        name: "青龙白虎",
        func: fun1,
      };
      let obj2 = {
        name: "朱雀玄武",
        o:obj
      };

      obj2.o.func();

显示绑定,区别

在代码中使用call,apply,bind来实现绑定

bind是返回一个函数,所以要再次调用

 let obj = {
        name: "成都校区",
      };
      let obj2 = {
        name: "马特里卡",
      };
      let obj3 = {
        name: "阿多比",
      };
      function func() {
        console.log(this.name);
      }
      func();  // 空
      func.call(obj);  // 成都校区
      func.apply(obj2);  // 马特里卡
 //   注意bind不会立即执行,会返回一个函数,因此要再次调用
      func.bind(obj3)();  // 阿多比
区别:

1.call、apply

f.call(新的this指向,参数1,参数2,参数3,...)
f.apply(新的this指向,[参数1,参数2,参数3,...])
// 两者的唯一区别就是参数,call是直接书写,以逗号间隔,apply是一个数组包裹

注意:apply,call会立即执行一次。

2.bind

f.bind(新的this指向,参数1,参数2,参数3,...)

f.bind()创建一个f具有相同函数体和作用域的函数,因此改变了指向后要再次调用一次,无论这个函数是如何被调用的。也就是说,bind只生效一次。


new 创建对象

this指向stu,谁创建实例this指向谁

 function Student() {
        this.name = "小明";

        console.log(this.name); // 小明
      }
      let stu1 = new Student();
       // age是挂在原型身上的,好处是就算new 100个Student原型上都只有一个age
            // 不会占用栈的空间,优化了内存
      stu1.__proto__.age = "18"; // 挂在原型上
      console.log(stu1);
this绑定的优先级

显示绑定>隐士绑定>默认绑定

new绑定>隐士绑定>默认绑定


箭头函数的this

es6的箭头函数是另类存在,箭头函数的this不适合前面的任何规则

箭头函数的this取决于外层作用域的this,外层函数this指向谁,箭头函数内部的this就指向谁

 function func() {
        //obj1
        return () => {
          console.log(this.name);
        };
      }
      let obj1 = {
        name: "成都",
      };
      let obj2 = {
        name: "武汉",
      };
      // 箭头函数this 外层的作用范围
    //   func()(); // window
      let bar = func.call(obj1);
        bar() //成都
        
      bar.call(obj2); //chengdu,指向最近的this
      bar.bind(obj2)(); //chengdu bind会再次调用
综合练习this
  var name = "window";
      let obj = {
        name: "obj",
        o: {
          name: "o",
          f: function () {
            return this.name;
          },
        },
        f: function () {
          return this.name;
        },
      };
      console.log(obj.o.f()); // o
      console.log(obj.f()); // obj
      let name1 = obj.f;   
      let name2 = obj.o;
      console.log(name1());  // window名字
      // window名字,因为this指向window,
    //   window对象有name属性叫window
      console.log(name2.f()); // o
      
          // 在js中我们都是从左读到右。于是this指向o而不是obj,这是一个很重要的区别
    // f()是被obj对象调用的,在这种情况,obj里的f函数返回this.name。this指向obj了,那obj就是返回值。
    // this关键词是在函数调用时才做绑定的,name1()前面是什么?什么都没有,因此this关键词就将指向全局window。
    // 因为f是name2调起的,而name2指向o,所以输出o

*箭头函数需要注意哪些地方?*

当要求动态上下文的时候,就不能够使用箭头函数,也就是this的固定化。

\1. 在使用=>定义函数的时候,this的指向是定义时所在的对象,而不是使用时所在的对象;

\2. 不能够用作构造函数,这就是说,不能够使用new命令,否则就会抛出一个错误。

\3. 不能够使用arguments对象;

\4. 不能使用yield命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值