javascript

js中的this

2018-12-05  本文已影响0人  little_short

前言

近期对this很感兴趣,于是乎简单整理了一些关于this的技术点,加深一下对this的理解。

非箭头函数

在非箭头函数下,this指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链,getter & setter等都适用;构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定,call & apply 方法等,容以下一步一步讨论。

解析

function f1(){
  return this;
}
f1() === window; // true
function f2(){
  "use strict"; // 这里是严格模式
  return this;
}
f2() === undefined; // true
//1
const o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};
console.log(o.f());  //37
const a = o.f;
console.log(a()):  //undefined
const o = {prop: 37};
function independent() {
  return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37

//2
o.b = {
  g: independent,
  prop: 42
};
console.log(o.b.g()); // logs 42
var o = {
  f : function(){ 
    return this.a + this.b; 
  }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
const o = {
  f : function(){ 
    return this.a + this.b; 
  }
};
const p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
function C(){
  this.a = 37;
}
const o = new C();
console.log(o.a); // logs 37
function C2(){
  this.a = 37;
  return {a:38};
}
const b = new C2();
console.log(b.a); // logs 38
function add(c, d){
  return this.a + this.b + c + d;
}
const 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);
}
tt.call(5);  // Number {[[PrimitiveValue]]: 5} 
tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
function f(){
  return this.a;
}

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

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

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

    // 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
    for(let i=0 ; i<elements.length ; i++){
      elements[i].addEventListener('click', bluify, false);
    }
<button onclick="console.log(this);">show me</button> //<button onclick="console.log(this);">show me</button> 
<button onclick="(function(){console.log(this)})()"></button> //window
<button onclick="(function(){'use strict';console.log(this)}())">use strict</button> //undefined
//默认情况下代码
function Person() {  
    this.age = 0;  
    setTimeout(function() {
        console.log(this);
    }, 3000);
}

const p = new Person();//3秒后返回 window 对象
==============================================
//通过bind绑定
function Person() {  
    this.age = 0;  
    setTimeout((function() {
        console.log(this);
    }).bind(this), 3000);
}
const p = new Person();//3秒后返回构造函数新生成的对象 Person{...}

规则

function fn() {
    console.log( this.a );
}
const a = 2;
fn(); // 2 -- fn单独调用,this引用window
function fn() {
    console.log( this.a );
}
var obj = {
    a: 2,
    fn: fn
};
obj.fn(); // 2 -- this引用obj。
function fn() {
     console.log( this.a );
 }
 var obj2 = {
     a: 42,
     fn: fn
 };
 var obj1 = {
     a: 2,
     obj2: obj2
 };
 obj1.obj2.fn(); // 42 -- this引用的是obj2.
function fn() {
     console.log( this.a );
 }
 var obj = {
     a: 2,
     fn: fn
 };
 var bar = obj.fn; // 函数引用传递
 var a = "全局"; // 定义全局变量
 bar(); // "全局"
function fn() {
     console.log( this.a );
 }
 var obj = {
     a: 2
 };
 fn.call( obj ); // 2
function fn() {
      console.log( this.a );
  }
  var obj = {
      a: 2
  };
 var a = 10;
 fn.call( null); // 10
function fn(a) {
    this.a = a;
}
var bar = new fn( 2 );
console.log( bar.a );// 2

用法

function test(){
    this.x = 1;
    alert(this.x);
  }
  test(); // 1
function test(){
  alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1
function test(){
    this.x = 1;
  }
  var o = new test();
  alert(o.x); // 1
    //运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变:
  var x = 2;
  function test(){
    this.x = 1;
  }
  var o = new test();
  alert(x); //2
var x = 0;
  function test(){
    alert(this.x);
  }
  var o={};
  o.x = 1;
  o.m = test;
  o.m.apply(); //0
//apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。如果把最后一行代码修改为
  o.m.apply(o); //1

箭头函数中的this

解析

function Person() {  
    this.age = 0;  
    setInterval(() => {
        // 回调里面的 `this` 变量就指向了期望的那个对象了
        this.age++;
    }, 3000);
}
const p = new Person();
const adder = {
  base : 1,
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },
  addThruCall: function inFun(a) {
    const f = v => v + this.base;
    const 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
const f = () => {'use strict'; return this};
const p = () => { return this};
console.log(1,f() === window);
console.log(2,f() === p());
//1 true
//2 true
const obj = {
     i: 10,
     b: () => console.log(this.i, this),
     c: function() {
       console.log( this.i, this)
     }
   }
   obj.b();  // undefined window{...}
   obj.c();  // 10 Object {...}
上一篇 下一篇

猜你喜欢

热点阅读