完全明白Javascript中的this

1 全局高低文中的this

在浏览器引擎的全局运转高低文中(在任何函数体外部),this 指代全局对象,不管是不是在严厉形式下。

<script>
    'use strict';
    console.log(this === window); // true
</script>
<script>
    console.log(this === window); // true
</script>

在node的全局高低文,发明this是一个空对象,不管是不是在严厉形式下。

在函数内部,this的值取决于函数是怎样挪用的。

2 直接挪用函数中的this
在非严厉的形式下,this的值默以为全局对象,window或许global。
在严厉形式下,this的值为undefined。

平常我们应用this的场景,都不是指代全局对象,所以涌现这类this是全局对象或许undefined的时刻 往往是我们出错了

<script>
    'use strict';
    function f1 () {
        console.log(this === window);
    }
    f1();// false
</script>
<script>
    function f1 () {
        console.log(this === window);
    }
    f1();// true
</script>

3 挪用对象要领中的this
当以对象的要领挪用函数时,函数中的this指向挪用该函数的要领

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};
console.log(o.f()); // logs 37
/**********************************/
  
var o = {prop: 37};
 
function independent() {
  return this.prop;
}
 
o.f = independent;
 
console.log(o.f()); // logs 37  //只取决于末了的函数挪用

函数的this指向挪用它的近来对象,这里independent函数中的this指向的是o.b 而不是o。

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

以下原型链和getter、setter中的this,都是挪用对象要领中this的场景。

之前犯过一个反过来的毛病,在一个对象中定义的要领中挪用this,然则运用要领的时刻没有经由历程对象挪用,所以this为undefined而不是本来的对象。

3.1 原型链中的 this

雷同的观点在定义在原型链中的要领也是一致的。假如该要领存在于一个对象的原型链上,那末this指向的是挪用这个要领的对象,表现得好像是这个要领就存在于这个对象上一样。

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

在这个例子中,对象p没有属于它自己的f属性,它的f属性继续自它的原型。然则这关于终究在o中找到f属性的查找历程来讲没有关系;查找历程首先从p.f的援用最先,所以函数中的this指向p。也就是说,由于f是作为p的要领挪用的,所以它的this指向了p。这是JavaScript的原型继续中的一个风趣的特征。

3.2 getter 与 setter 中的 this

再次,雷同的观点也适用时的函数作为一个 getter 或许 一个setter挪用。作为getter或setter函数都邑绑定 this 到从设置属性或获得属性的谁人对象。

function modulus(){
  return Math.sqrt(this.re * this.re + this.im * this.im);
}
 
var o = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};
 
Object.defineProperty(o, 'modulus', {
  get: modulus, enumerable:true, configurable:true});
 
console.log(o.phase, o.modulus); // logs -0.78 1.414

4 组织函数中的 this

当一个函数被作为一个组织函数来运用(运用new关键字),它的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};
}
 
o = new C2();
console.log(o.a); // logs 38

在末了的例子中(C2),由于在挪用组织函数的历程当中,手动的设置了返回对象,与this绑定的默许对象被作废(本质上这使得语句“this.a = 37;”成了“僵尸”代码,实际上并非真正的“僵尸”,这条语句实行了然则关于外部没有任何影响,因而完全能够疏忽它)。

5 call 和 apply

call和apply能够指定函数实行时this的指向。

当一个函数的函数体中运用了this关键字时,经由历程一切函数都从Function对象的原型中继续的call()要领和apply()要领挪用时,它的值能够绑定到一个指定的对象上。

function add(c, d){
  return this.a + this.b + c + d;
}
 
var o = {a:1, b:3};
 
// The first parameter is the object to use as 'this', subsequent parameters are passed as
// arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
 
// The first parameter is the object to use as 'this', the second is an array whose
// members are used as the arguments in the function call
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

运用 call 和 apply 函数的时刻要注重,假如通报的 this 值不是一个对象,JavaScript 将会尝试运用内部 ToObject 操纵将其转换为对象。因而,假如通报的值是一个原始值比方 7 或 ‘foo’ ,那末就会运用相干组织函数将它转换为对象,所以原始值 7 经由历程new Number(7)被转换为对象,而字符串’foo’运用 new String(‘foo’) 转化为对象,比方:

function bar() {
  console.log(Object.prototype.toString.call(this));
}
 
bar.call(7); // [object Number]

6 bind 要领

ECMAScript 5 引入了 Function.prototype.bind。挪用f.bind(someObject)会建立一个与f具有雷同函数体和作用域的函数,然则在这个新函数中,this将永远地被绑定到了bind的第一个参数,不管这个函数是怎样被挪用的。

能够看到,call和apply是不转变本来的函数,只是在实行的时刻指定函数的this,而bind要领则是生成了一个this指向牢固的函数,

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

在ES6的语法中,箭头函数默许绑定当前函数声明环境的this。

7 DOM事宜处置惩罚函数中的 this

当函数被用作事宜处置惩罚函数时,它的this指向函数所绑定的DOM对象。

event.currentTarget指向事宜所绑定的元素,而event.target一直指向事宜发作时的元素
所以this 一直和 event.currentTarget 雷同。

<body>
    <div id="wrapper" style="height:200px; background: red">
        <input id="inner" type="button" value="inner" />
    </div>
</body>
<script>
    function func1 (e) {
        console.log('wrapper')
        console.log('this');
        console.log(this);
        console.log("e.target");
        console.log(e.target);
        console.log('e.currentTarget');
        console.log(e.currentTarget);
    }
    function func2 (e) {
        console.log('inner')
        console.log('this');
        console.log(this);
        console.log("e.target");
        console.log(e.target);
        console.log('e.currentTarget');
        console.log(e.currentTarget);
    }
    document.getElementById("wrapper").addEventListener('click',func1);
    document.getElementById("inner").addEventListener('click',func2);
</script>

8 内联事宜处置惩罚函数中的 this

当代码被内联处置惩罚函数挪用时,它的this指向监听器地点的DOM元素:

<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>
//上面的alert会显现button。注重只要外层代码中的this是如许设置。

<button onclick="alert((function(){return this})());">
  Show inner this
</button>

在这类情况下,没有设置内部函数的 this,所以它指向 global/window 对象(即非严厉形式下挪用的函数未设置 this 时指向的默许对象)。

本文绝大多数内容参考自: https://developer.mozilla.org…
仅作少量修正

    原文作者:传播正能量
    原文地址: https://segmentfault.com/a/1190000007906845
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞