this 的指向问题

事件调用环境

谁触发事件,函数里面的this指向的就是谁。

.box1, .box2 {
  width: 100px;
  height: 100px;
  border: 1px solid black;
  background: #0A8CD2;
  position: relative;
  left: 0;
  transition: 1s;
}
<div class="box1"></div>
<div class="box2"></div>
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;

function move() {
  this.style.left = '100px';
}

全局环境

  • 浏览器
    window
    console.log(this);  // Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
    
  • node
    module.exports
    console.log(this === module.exports);   // true
    

函数内部

  • this最终指向的是调用它的对象
    • 普通函数直接调用与window调用
    • 对象中的函数直接调用与window调用
.box1, .box2 {
  width: 100px;
  height: 100px;
  border: 1px solid black;
  background: #0A8CD2;
  position: relative;
  left: 0;
  transition: 1s;
}
<div class="box1"></div>
<div class="box2"></div>
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;

function move() {
  console.log(this); 
  this.style.left = '100px';
}

move(); // Window;    严格模式下:undefined
window.more() // 使用这个方法调用,严格模式下也是 Window

// var abc = 10;
// console.log(window);
  • 函数被多层对象所包含,如果函数被最外层对象调用,this指向的也只是它上一级的对象
    • 多层对象中的函数的this指向
    • 对象中的函数被赋值给另一个变量
var obj = {
  a: 10,
  b: function () {
    console.log(this);
  }
}
obj.b();
window.obj.b();
  • 构造函数中的this指向的是实例对象
    • 构造函数中的this指向
    • new运算符的作用
function fn() {
  this.num = 10;
  console.log(this);
}

var obj = new fn();
console.log(obj);

/*
   1. 调用函数
   2. 自动创建一个对象
   3. 把创建出来的对象和this进行绑定
   4. 如果构造函数没有返回值,隐式返回this对象
*/
function fn() {
    this.num = 10;
    console.log(this);
  }

  fn.num = 20;
  fn.prototype.num = 30;
  fn.prototype.method = function () {
    console.log(this.num);

  }

  var prototype = fn.prototype;
  var method = prototype.method;

  // 调用环境不同,this的指向不同
  // 举例:
  // 1.
  new fn().method(); // 10

  // {}.methods();


  // 2.
  prototype.method(); // 30

  // fn.prototype = {}

  /*
    var obj = {};
    obj.x = 10;
    obj.fn = function () {
      console.log(this.x);
    }
    obj.fn(); // 10
    // 此写法相当于下面那种写法

    var obj = {
      x: 10,
      fn: function () {
        console.log(this);
      }
    }
  */


  // 3.
  method(); // undefined

  /*
    var obj = {};
    obj.x = 10;
    obj.fn = function () {
      console.log(this.x);
    }

    var abc = obj.fn();
    abc(); // Window
  */
  • 如果构造函数中有return         如果return的值是对象,this指向返回的对象;如果不是对象,则this指向保持原来的规则。 (null比较特殊)
function fn() {
  this.num = 10;
  return '';
  /*
    return 1;
    return null;
  */
}

var obj = new fn();
console.log(obj.num); // 10

//

function fn() {
  this.num = 10;
  return [];
  /*
    return {};
    return function(){};
  */
}

var obj = new fn();
console.log(obj.num); // undefined

箭头函数

  • 箭头函数本身是没有this和arguments的,在箭头函数中引用this实际上调用的是定义这个箭头函数的上一层作用域的this。(是上一层作用域,因对象是不能形成独立的作用域的)
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;

function move() {
  setTimeout(function () {
    this.style.left = '100px';
  }, 1000)
}
// Uncaught TypeError: Cannot set property 'left' of undefined
// this是指向window的

// 改进方法
function move() {
  var _this = this;
  setTimeout(function () {
    _this.style.left = '100px';
  }, 1000)
}

// 用箭头函数更方便!
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;

function move() {
  setTimeout(() => {
    this.style.left = '100px';
  }, 1000)
}

修改this指向

  • call(this,a,b,c)
  • apply(this,[a,b,c])
  • bind(this,a,b,c)()
  var box = document.querySelector('.box'),
    a, b, c;
  var obj = {
    // fn: () => {
    //   console.log(this);
    // }
    // 箭头函数在定义的时候就已经决定了this的指向,不能用call等修改

    fn: function () {
      console.log(this);
    }
  }
  
  obj.fn.call(box, a, b, c);
  obj.fn.apply(box, [a, b, c]);
  obj.fn.bind(box)();
<div class="box"></div>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页