this指向问题

1、全局环境下

在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;

1 this.a = 37;
2 window.a // 37

 

2. 函数上下文调用

1) 、函数直接调用

普通函数内部的this分两种情况,严格模式和非严格模式

非严格模式下,this指向全局对象window

1 function fn(){
2    return this;  
3 }
4 
5 fn === window;  // true

 严格模式下,this为undefined

function foo(){
  "use strict";
  return this;    
}

foo === undefined; // true

2)、对象中的this

对象内部方法的this指向调用这些方法的对象

  1. 函数的定义位置不影其this的指向,this指向只和调用函数的对象有关。

  2. 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象,而非window)。

// 第一种
var o = {
  prop: 37,
  f: function() {
  console.log(this);
    return this.prop;
  }
};
console.log(o.f());  //37
var a = o.f;         // this 指向window
console.log(a());  //undefined

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37

// 第二种
o.b = {
  g: independent,
  prop: 42
};
console.log(o.b.g()); // logs 42

3)、原型链中this

原型链中的方法的this任然指向调用它的对象

 

可以看出, 在p中没有属性f,当执行p.f()时,会查找p的原型链,找到 f 函数并执行,但这与函数内部this指向对象 p 没有任何关系,只需记住谁调用指向谁。

以上对于函数作为getter & setter 调用时同样适用。

4)、构造函数中this

构造函数中this与被创建的新对象绑定。

注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

function C(){
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37


function C2(){
  this.a = 37;
  return {a:38};
}

var b = new C2();
console.log(b.a); // logs 38

5)、call & apply 

当函数通过Function对象的原型中继承的方法call() 和apply() 方法调用时,其函数内部的this值可以绑定到call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,Jacascript内部会尝试将其转换成对象然后指向它。

 

function add(c, d){
  return this.a + this.b + c + d;
}

var o = {a:1, b:3};

add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

function tt() {
  console.log(this);
}
// 返回对象见下图(图1)
tt.call(5);  // Number {[[PrimitiveValue]]: 5} 
tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}

6)、bind方法

bind方法在ES5引入, 在Function的原型链上,Function.prototype.bind。通过bind方法绑定后,函数将永远绑定在其第一个参数对象上,而无论在什么情况下被调用。

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty

3、DOM事件处理函数中的this& 内联事件中的this

DOM 事件处理函数

1. 当函数被当作间挺事件处理函数时,其this,指向处罚该事件的元素(针对addEventListener事件)

  // 被调用时,将关联的元素变成蓝色
    function bluify(e){
      //在控制台打印出所点击元素
      console.log(this);
      //阻止时间冒泡
      e.stopPropagation();
      //阻止元素的默认事件
      e.preventDefault();      
      this.style.backgroundColor = '#A5D9F3';
    }

    // 获取文档中的所有元素的列表
    var elements = document.getElementsByTagName('*');

    // 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
    for(var i=0 ; i<elements.length ; i++){
      elements[i].addEventListener('click', bluify, false);
    }

2.内联事件

内联事件中的this指向分两种情况

  * 当代码被内联处理函数调用时,它的this指向监听所在的DOM元素

  * 当代码被包括在函数内部执行时,其this指向等同于*****函数直接调用情况*****,即在非严格模式指向全局对象window,严格模式指向undefined

3、setTimeout & setInterval

对于延时函数内部的回调函数的this指向全局对象window(当然我们可以通过bind方法改变其内部函数的this指向)

//默认情况下代码
function Person() {  
    this.age = 0;  
    setTimeout(function() {
        console.log(this); // window
    }, 3000);
}

var p = new Person();//3秒后返回 window 对象
==============================================
//通过bind绑定
function Person() {  
    this.age = 0;  
    setTimeout((function() {
        console.log(this); // p 对象
    }).bind(this), 3000);
}

var p = new Person();//3秒后返回构造函数新生成的对象 Person{...}

4、箭头函数中的this

由于箭头函数不绑定this,它会捕获其所在(即定义的位置)上下文的this的值,作为自己的this值

 1)、所以call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的this毫无影响。

 2)、考虑到this时词法层面上的,严格模式中与this相关的规则都将被忽略。(可以忽略是否在严格模式下的影响)

var adder = {
  base : 1,
    
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function inFun(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };
            
    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3,其内部的this并没有因为call() 而改变,其this值仍然为函数inFun的this值,指向对象adder

箭头函数this指向全局window对象,而普通函数则指向调用它的对象

转载来源 http://www.cnblogs.com/dongcanliang/p/7054176.html

posted @ 2019-03-19 14:33  Sweet's  阅读(94)  评论(0编辑  收藏  举报