this指向问题

this的指向

全局作用域中的this

指向它本身

函数中的this

函数中this的指向,是在函数被调用的时候确定的

函数被调用时,会产生一个执行上下文,执行上下文被创建的时候会做几件事情:创建变量对象;确定作用域链,确定this指向

在函数执行过程中,this一旦被确定,就不可更改了

      var name = "kaka";
      var obj = { name: "lulu" };
      function test1() {
        this=obj  // 报错 Uncaught SyntaxError: Invalid left-hand side in assignment
        console.log(this.name);
      }
      test1();

普通函数

如果调用者函数,被某一个对象所拥有(作为对象的方法),那么该函数在调用时,内部的this指向该对象(函数的调用者)。如果函数独立调用,那么该函数内部的this指向undefined;再非严格模式下,当this指向undefined和null时,会被默认指向全局对象

      var a = 20;
      var obj = {
        a: 10,
        c: this.a + 20,
        fn: function () {
          // "use strict";
          return this.a;
        },
      };
      console.log(obj.c);
      console.log(obj.fn());
      var func = obj.fn;
      console.log(func());
      console.log(window.func());

在非严格模式下输出结果是:40 10 20 20

在严格模式下输出结果是:40 20 报错:undefined没有a属性 20(由于前面报错没有打印)

obj虽然有{},但是他并没有产生一个独立上下文,没有产生一个函数作用域,所以this指向是全局对象

构造函数

构造函数中的this指向实例对象

      function Person(name, age) {
        this.name = name;
        this.age = age;
        console.log(this);   // {name:"潘周聃",age:29}
      }
      var p = new Person("潘周聃", 29);

箭头函数

箭头函数没有自己的this,this始终沿着作用域链向上找,它实在函数定义是确定的,而不是执行时,也就是箭头函数所在的执行上下文创建的时候,确定了箭头函数中this的指向

箭头函数中的this会保留在定义该函数时的上下文

King被调用的时候产生了一个上下文,箭头函数定义是在这个上下文中;所以这里的this指向实例对象

      var name = "潘周聃,";
      var content = "男,29岁";
      function King(name, content) {
        this.name = name;
        this.content = content;
        setTimeout(() => {
          console.log(this.name + this.content);  // 欧豪,", "你是我的神"
        }, 0);
      }
      const k = new King("欧豪,", "你是我的神");

如果我们使用普通函数,this指向全局对象

      var name = "潘周聃,";
      var content = "男,29岁";
      function King(name, content) {
        this.name = name;
        this.content = content;
        setTimeout(function () {
          console.log(this.name + this.content);  // 潘周聃,男,29岁
        }, 0);
      }
      const k = new King("欧豪,", "你是我的神");

再来一个例子

    
这是一个div
const dom = document.getElementsByClassName("good")[0]; dom.addEventListener("click", () => { console.log(this, "箭头函数"); // this指向全局对象Window }); dom.addEventListener("click", function () { console.log(this, "普通函数"); // this指向dom,函数的调用者 });

修改函数的this指向

call

fn.call(targetObj,param1,param2……)

      var name = "kaka";
      var obj = { name: "lulu" };
      function test1() {
        console.log(this.name);
      }
      test1.call(obj);  // 控制台输出"lulu"

会自动执行一次函数,改变函数中的this指向;

参数以参数序列的形式传递,第一个参数是this要指向的对象,后面是函数的参数

      var name = "kaka";
      var obj = { name: "lulu" };
      function test1(num1, num2) {
        console.log(this.name);    // lulu
        console.log(num1 - num2);  // 8
      }
      test1.call(obj, 10, 2);

apply

fn.apply(targetObj,[params])

​      var name = "kaka";
​      var obj = { name: "lulu" };
​      function test1(num1, num2) {
​        console.log(this.name);   // lulu
​        console.log(num1 - num2);  // 8
​      }
​      test1.apply(obj, [10, 2]);

会自动执行一次函数,改变函数中的this指向

和bind一样,只是传递给函数的参数不一样,apply以数组的形式传参

bind

bind返回的是函数

// 这是错误的写法
      var name = "kaka";
      var obj = { name: "lulu" };
      function test1(num1, num2) {
        console.log(this.name);  // kaka
        console.log(num1 - num2);  // NaN
      }
      test1.bind(obj, 10, 2);
      test1();

因为test1函数中的this是在函数被调用的时候确定的,bind会返回一个函数,但是并没有调用函数;函数真正被调用的时候this指向undefined,非严格模式下指向全局对象,所以是打印kaka

bind不会自动调用一次函数,其他和call一样的

// 正确方式
      var name = "kaka";
      var obj = { name: "lulu" };
      function test1(num1, num2) {
        console.log(this.name);    // lulu
        console.log(num1 - num2);  // 8
      }
      const bindFn = test1.bind(obj, 10, 2);
      bindFn();  // 或者test1.bind(obj, 10, 2)();

你可能感兴趣的:(js基础,前端,javascript)