www.bifa88.com 2

JavaScript中this关键词的选取本事,的运转机制及爬坑指南

JavaScript 中 this 的运维机制及爬坑指南

2018/03/14 · JavaScript
· this

原稿出处: [Dr. Axel

要依附this 所在的职位来明白它,景况大意能够分为三种:

要凭仗this 所在的职位来掌握它,情形大要能够分为三种:

Rauschmayer]()   译文出处:[众成翻译

woolll]()   

www.bifa88.com 1

在 JavaScript 中,this 这么些尤其的变量是对峙比较复杂的,因为 this
不仅仅用在面向对象遭逢中,在别的任哪个地方方也是可用的。 本篇博文中会解释
this 是何许做事的以及接纳中可能产生难点的地点,最后奉上最棒施行。

为了越来越好驾驭 this,将 this 使用的现象分成三类:

  • 在函数内部 this 一个外加的,平常是带有的参数。
  • 在函数外部(超级功效域中): 那指的是浏览器中的全局对象恐怕Node.js 中三个模块的出口。
  • 在传递给eval()的字符串中: eval() 大概赚取 this
    当前值值,恐怕将其设置为全局对象,取决于 this
    是直接调用依然直接调用。

大家来看望各样门类。

  一、在函数中:this 平常是二个富含的参数。

  一、在函数中:this 平日是二个包括的参数。

this 在函数中

那是最常用的 this 使用形式,函数通过扮演三种差异的剧中人物来代表 JavaScript
中的全体可调用结构体:

  • 普通函数(this 在非严厉方式下为全局对象,在严格方式下为undefined)
  • 构造函数(this 指向新创建的实例)
  • 方式(this 是指方法调用的收信人)

在函数中,this 平时被感觉是一个外加的,隐含的参数。

  2、在函数外(一流作用域中):在浏览器中this
指的是全局对象;在Node.js中指的是模块(module)的导出(exports)。

  二、在函数外(拔尖功能域中):在浏览器中this
指的是大局对象;在Node.js中指的是模块(module)的导出(exports)。

this 在平凡函数中

在一般函数中,this
的值取决于模式:

  • 非严峻方式: this
    是指向大局对象
    (在浏览器中为window对象)。
function sloppyFunc() { console.log(this === window); // true }
sloppyFunc();

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6bfd7bd4d414140440-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6bfd7bd4d414140440-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6bfd7bd4d414140440-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6bfd7bd4d414140440-4">
4
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6bfd7bd4d414140440-1" class="crayon-line">
function sloppyFunc() {
</div>
<div id="crayon-5b8f6bfd7bd4d414140440-2" class="crayon-line crayon-striped-line">
    console.log(this === window); // true
</div>
<div id="crayon-5b8f6bfd7bd4d414140440-3" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6bfd7bd4d414140440-4" class="crayon-line crayon-striped-line">
sloppyFunc();
</div>
</div></td>
</tr>
</tbody>
</table>

  • 严俊情势: this 的值为 undefined。
function strictFunc() { 'use strict'; console.log(this ===
undefined); // true } strictFunc();

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6bfd7bd58954780524-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6bfd7bd58954780524-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6bfd7bd58954780524-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6bfd7bd58954780524-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6bfd7bd58954780524-5">
5
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6bfd7bd58954780524-1" class="crayon-line">
function strictFunc() {
</div>
<div id="crayon-5b8f6bfd7bd58954780524-2" class="crayon-line crayon-striped-line">
   'use strict';
</div>
<div id="crayon-5b8f6bfd7bd58954780524-3" class="crayon-line">
   console.log(this === undefined); // true
</div>
<div id="crayon-5b8f6bfd7bd58954780524-4" class="crayon-line crayon-striped-line">
}
</div>
<div id="crayon-5b8f6bfd7bd58954780524-5" class="crayon-line">
strictFunc();
</div>
</div></td>
</tr>
</tbody>
</table>

也正是说,this 是二个设定了默许值(window或undefined)的隐式参数。
不过,能够透过 call() 或 apply() 举办函数调用,并强烈钦命this的值:“

function func(arg1, arg2) { console.log(this); // a console.log(arg1);
// b console.log(arg2); // c } func.call(‘a’, ‘b’, ‘c’); // (this, arg1,
arg2) func.apply(‘a’, [‘b’, ‘c’]); // (this, arrayWithArgs)

1
2
3
4
5
6
7
function func(arg1, arg2) {
        console.log(this); // a
        console.log(arg1); // b
        console.log(arg2); // c
    }
func.call(‘a’, ‘b’, ‘c’); // (this, arg1, arg2)
func.apply(‘a’, [‘b’, ‘c’]); // (this, arrayWithArgs)

  三、传递到eval()中的字符串:借使eval()是被直接调用的,this
指的是时下目标;若是eval()是被直接调用的,this 就是指全局对象。

  叁、传递到eval()中的字符串:假诺eval()是被直接调用的,this
指的是时下目的;假设eval()是被直接调用的,this 正是指全局对象。

this 在构造函数中

壹经经过new运算符调用函数,则函数将改为构造函数。
该运算符制造一个新的对象,并通过它通过this传递给构造函数:“

var savedThis; function Constr() { savedThis = this; } var inst = new
Constr(); console.log(savedThis === inst); // true

1
2
3
4
5
6
var savedThis;
function Constr() {
   savedThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

在JavaScript中实现,new运算符大概如下所示(更标准的落成稍稍复杂一点):

function newOperator(Constr, arrayWithArgs) { var thisValue =
Object.create(Constr.prototype); Constr.apply(thisValue, arrayWithArgs);
return thisValue; }

1
2
3
4
5
function newOperator(Constr, arrayWithArgs) {
   var thisValue = Object.create(Constr.prototype);
   Constr.apply(thisValue, arrayWithArgs);
   return thisValue;
}

  对那个分类,大家做了对应的测试:
  一、在函数中的this

  对这多少个分类,大家做了相应的测试:
  一、在函数中的this

this 在措施中

在格局中,类似于守旧的面向对象的语言:this指向接受者,方法被调用的靶子。

var obj = { method: function () { console.log(this === obj); // true } }
obj.method();

1
2
3
4
5
6
var obj = {
    method: function () {
    console.log(this === obj); // true
}
}
obj.method();

  函数基本能够代表JS中存有可被调用的布局,所以那是也最常见的选取this
的场地,而函数又能被子分为下列三种角色:

  函数基本能够代表JS中负有可被调用的构造,所以那是也最普及的行使this
的情景,而函数又能被子分为下列三种剧中人物:

this 在超级效率域中

在浏览器中,顶层作用域是全局成效域,它指向global
object(如window):

console.log(this === window); // true

1
console.log(this === window); // true

在Node.js中,平时在模块中实践代码。
因此,超级作用域是三个诡异的模块功效域

// `global` (不是 `window`) 指全局对象: console.log(Math ===
global.Math); // true // `this` 不指向全局对象: console.log(this !==
global); // true // `this` refers to a module’s exports:
console.log(this === module.exports); // true

1
2
3
4
5
6
7
// `global` (不是 `window`) 指全局对象:
console.log(Math === global.Math); // true
 
// `this` 不指向全局对象:
console.log(this !== global); // true
// `this` refers to a module’s exports:
console.log(this === module.exports); // true

    实函数
    构造器
    方法

    实函数
    构造器
    方法

this 在 eval() 中

eval() 可以被_直接(通过真正的函数调用)或间接_(通过其它方法)。
详细分解在这里。

固然直接调用evaleval()
,则this指向大局对象:“

(0,eval)(‘this === window’) true

1
2
(0,eval)(‘this === window’)
true

要不,假若直白调用eval() ,则this与eval()的条件中保持一致。 举例:

// 普通函数 function sloppyFunc() { console.log(eval(‘this’) ===
window); // true } sloppyFunc(); function strictFunc() { ‘use strict’;
console.log(eval(‘this’) === undefined); // true } strictFunc(); //
构造器 var savedThis; function Constr() { savedThis = eval(‘this’); }
var inst = new Constr(); console.log(savedThis === inst); // true //
方法 var obj = { method: function () { console.log(eval(‘this’) ===
obj); // true } } obj.method();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 普通函数
function sloppyFunc() {
    console.log(eval(‘this’) === window); // true
}
sloppyFunc();
 
function strictFunc() {
    ‘use strict’;
    console.log(eval(‘this’) === undefined); // true
}
strictFunc();
 
// 构造器
var savedThis;
function Constr() {
     savedThis = eval(‘this’);
}
var inst = new Constr();
console.log(savedThis === inst); // true
 
// 方法
var obj = {
method: function () {
     console.log(eval(‘this’) === obj); // true
}
}
obj.method();

  1.1  在实函数中的this

  壹.壹  在实函数中的this

与this相关的陷阱

有四个你须要掌握的与this相关的牢笼。请小心,在种种景况下,严刻形式更安全,因为this在普通函数中为undefined,并且会在产出难点时告诫。

  在实函数中,this 的值是在乎它所处的上下文的情势。

  在实函数中,this 的值是取决于它所处的上下文的方式。

陷阱:忘记new操作符

只要你调用1个构造函数时忘记了new操作符,那么您意想不到地将this用在3个一般的函数。this会未有科学的值。
在非严厉形式下,this指向window对象,你将创立全局变量:

function Point(x, y) { this.x = x; this.y = y; } var p = Point(7, 5); //
忘记new! console.log(p === undefined); // true // 创立了全局变量:
console.log(x); // 七 console.log(y); // 5

1
2
3
4
5
6
7
8
9
10
function Point(x, y) {
    this.x = x;
    this.y = y;
}
var p = Point(7, 5); // 忘记new!
console.log(p === undefined); // true
 
// 创建了全局变量:
console.log(x); // 7
console.log(y); // 5

有幸的,在严峻形式下会获得警示(this === undefined):

function Point(x, y) { ‘use strict’; this.x = x; this.y = y; } var p =
Point(7, 5); // TypeError: Cannot set property ‘x’ of undefined

1
2
3
4
5
6
7
function Point(x, y) {
    ‘use strict’;
    this.x = x;
    this.y = y;
}
var p = Point(7, 5);
// TypeError: Cannot set property ‘x’ of undefined

  Sloppy情势:this 指的是全局对象(在浏览器中就是window)。

  Sloppy格局:this 指的是大局对象(在浏览器中正是window)。

陷阱:不科学地领到形式

假定获得格局的值(不是调用它),则可以将该办法转变为函数。
调用该值将招致函数调用,而不是方法调用。
当将艺术作为函数或方式调用的参数字传送递时,也许会发生那种提取。
实际例子包蕴setTimeout()和事件注册管理程序。 我将使用函数callItt()
来模拟此用例:

/**类似setTimeout() 和 setImmediate() */ function callIt(func) {
func(); }

1
2
3
4
/**类似setTimeout() 和 setImmediate() */
function callIt(func) {
      func();
}

只要在非严厉方式下把三个格局作为函数来调用,那么this将针对大局对象并创立全局变量:

var counter = { count: 0, // Sloppy-mode method inc: function () {
this.count++; } } callIt(counter.inc); // Didn’t work:
console.log(counter.count); // 0 // Instead, a global variable has been
created // (NaN is result of applying ++ to undefined):
console.log(count); // NaN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var counter = {
    count: 0,
// Sloppy-mode method
inc: function () {
          this.count++;
    }
  }
 
callIt(counter.inc);
 
// Didn’t work:
console.log(counter.count); // 0
 
// Instead, a global variable has been created
// (NaN is result of applying ++ to undefined):
console.log(count);  // NaN

假如在严刻格局下把2个方法作为函数来调用,this为undefined。
同时会获取一个警戒:

var counter = { count: 0, // Strict-mode method inc: function () { ‘use
strict’; this.count++; } } callIt(counter.inc); // TypeError: Cannot
read property ‘count’ of undefined console.log(counter.count);

1
2
3
4
5
6
7
8
9
10
11
12
13
var counter = {
        count: 0,
        // Strict-mode method
        inc: function () {
            ‘use strict’;
            this.count++;
        }
    }
 
callIt(counter.inc);
 
// TypeError: Cannot read property ‘count’ of undefined
console.log(counter.count);

纠正方法是应用[bind()](http://speakingjs.com/es5/ch17.html\#Function.prototype.bind):
The fix is to use
bind():

var counter = { count: 0, inc: function () { this.count++; } }
callIt(counter.inc.bind(counter)); // 成功了!
console.log(counter.count); // 1

1
2
3
4
5
6
7
8
9
10
11
var counter = {
    count: 0,
    inc: function () {
          this.count++;
        }
    }
 
callIt(counter.inc.bind(counter));
 
// 成功了!
console.log(counter.count); // 1

bind()成立了二个新的函数,它总是接收八个对准counter的this。

复制代码 代码如下:

复制代码 代码如下:

陷阱:shadowing this

当在贰个措施中选用普通函数时,很轻巧忘记前者具备其协和this(尽管其无需this)。
由此,你无法在此以前端引用该措施的this,因为该this会被遮挡。
让大家看看出现难点的例子:

var obj = { name: ‘Jane’, friends: [ ‘Tarzan’, ‘Cheeta’ ], loop:
function () { ‘use strict’; this.friends.forEach( function (friend) {
console.log(this.name+’ knows ‘+friend); } ); } }; obj.loop(); //
TypeError: Cannot read property ‘name’ of undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var obj = {
        name: ‘Jane’,
        friends: [ ‘Tarzan’, ‘Cheeta’ ],
        loop: function () {
            ‘use strict’;
            this.friends.forEach(
                function (friend) {
                    console.log(this.name+’ knows ‘+friend);
                }
            );
        }
    };
obj.loop();
// TypeError: Cannot read property ‘name’ of undefined

在前面的例证中,获取this.name战败,因为函数的this个是undefined,它与格局loop()的例外。
有三种艺术能够查对this。

修正1: that = this。
将它分配给四个平昔不被遮挡的变量(另二个盛行名称是self)并采纳该变量。

loop: function () { ‘use strict’; var that = this;
this.friends.forEach(function (friend) { console.log(that.name+’ knows
‘+friend); }); }

1
2
3
4
5
6
7
loop: function () {
        ‘use strict’;
        var that = this;
        this.friends.forEach(function (friend) {
            console.log(that.name+’ knows ‘+friend);
        });
    }

修正2: bind()。
使用bind()来创制八个this总是指向正确值的函数(在底下的例证中该方法的this)。

loop: function () { ‘use strict’; this.friends.forEach(function (friend)
{ console.log(this.name+’ knows ‘+friend); }.bind(this)); }

1
2
3
4
5
6
loop: function () {
     ‘use strict’;
      this.friends.forEach(function (friend) {
          console.log(this.name+’ knows ‘+friend);
    }.bind(this));
}

修正3: forEach的第二个参数。
此方法具备第3个参数,this值将作为此值传递给回调函数。

loop: function () { ‘use strict’; this.friends.forEach(function (friend)
{ console.log(this.name+’ knows ‘+friend); }, this); }

1
2
3
4
5
6
loop: function () {
     ‘use strict’;
     this.friends.forEach(function (friend) {
      console.log(this.name+’ knows ‘+friend);
     }, this);
}

function sloppyFunc() {
    console.log(this === window); // true
}
sloppyFunc();

function sloppyFunc() {
    console.log(this === window); // true
}
sloppyFunc();

极品施行

从概念上讲,作者感觉一般函数未有它和煦的this,并且想到上述修复是为了保障那种主见。
ECMAScript
陆因而[箭头函数](http://2ality.com/2013/04/arrow-functions.html)协助那种方法
– 未有它们自个儿的this。
在这么的函数里面,你能够随心所欲使用this,因为不会被挡住:

loop: function () { ‘use strict’; // The parameter of forEach() is an
arrow function this.friends.forEach(friend => { // `this` is loop’s
`this` console.log(this.name+’ knows ‘+friend); }); }

1
2
3
4
5
6
7
8
loop: function () {
    ‘use strict’;
     // The parameter of forEach() is an arrow function
    this.friends.forEach(friend => {
     // `this` is loop’s `this`
     console.log(this.name+’ knows ‘+friend);
     });
}

小编不希罕使用this作为日常函数的增大参数的API:

beforeEach(function () { this.addMatchers({ toBeInRange: function
(start, end) { … } }); });

1
2
3
4
5
6
7
beforeEach(function () {  
   this.addMatchers({  
   toBeInRange: function (start, end) {  
    …
    }  
   });  
});

将如此的蕴藏参数形成惹人注目的参数使得业务更是综上说述,并且与箭头函数包容。

beforeEach(api => { api.addMatchers({ toBeInRange(start, end) { … }
}); });

1
2
3
4
5
6
7
beforeEach(api => {
   api.addMatchers({
    toBeInRange(start, end) {
       …
     }
  });
});

JavaScript
浏览器
HTTP
HTML
ECMAScript
6


1 赞 2 收藏
评论

www.bifa88.com 2

Strict模式:this 的值是undefined。

Strict模式:this 的值是undefined。

复制代码 代码如下:

复制代码 代码如下:

function strictFunc() {
    ‘use strict’;
    console.log(this === undefined); // true
}
strictFunc();

function strictFunc() {
    ‘use strict’;
    console.log(this === undefined); // true
}
strictFunc();

this
是函数的盈盈参数,所以它的值总是同样的。可是你是能够经过行使call()恐怕apply()的章程展现地定义好this的值的。

this
是函数的盈盈参数,所以它的值总是同样的。然而你是足以由此采取call()或许apply()的办法突显地定义好this的值的。

复制代码 代码如下:

复制代码 代码如下:

function func(arg1, arg2) {
    console.log(this); // 1
    console.log(arg1); // 2
    console.log(arg2); // 3
}
func.call(1, 2, 3); // (this, arg1, arg2)
func.apply(1, [2, 3]); // (this, arrayWithArgs)

function func(arg1, arg2) {
    console.log(this); // 1
    console.log(arg1); // 2
    console.log(arg2); // 3
}
func.call(1, 2, 3); // (this, arg1, arg2)
func.apply(1, [2, 3]); // (this, arrayWithArgs)

1.二  构造器中的this

一.二  构造器中的this

  你能够因此new 将贰个函数当做1个结构器来使用。new
操作成立了一个新的对象,并将以此目的通过this 传入构造器中。

  你能够经过new 将3个函数当做二个组织器来使用。new
操作创立了3个新的对象,并将以此目的通过this 传入构造器中。

复制代码 代码如下:

复制代码 代码如下:

var savedThis;
function Constr() {
    savedThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

var savedThis;
function Constr() {
    savedThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

JS中new
操作的得以达成原理大约如上面包车型大巴代码所示(校订确的完成请看这里,这一个达成也相比复杂一些):

JS中new
操作的达成原理大约如上面包车型客车代码所示(越来越纯粹的兑现请看这里,那么些完成也比较复杂一些):

复制代码 代码如下:

复制代码 代码如下:

function newOperator(Constr, arrayWithArgs) {
    var thisValue = Object.create(Constr.prototype);
    Constr.apply(thisValue, arrayWithArgs);
    return thisValue;
}

function newOperator(Constr, arrayWithArgs) {
    var thisValue = Object.create(Constr.prototype);
    Constr.apply(thisValue, arrayWithArgs);
    return thisValue;
}

1.三  方法中的this

壹.三  方法中的this

  在艺术中this 的用法更倾向于古板的面向对象语言:this
指向的接收方,也正是包涵有那个点子的目标。

  在格局中this 的用法更赞成于守旧的面向对象语言:this
指向的接收方,也正是包涵有那个方法的对象。

复制代码 代码如下:

复制代码 代码如下:

var obj = {
    method: function () {
        console.log(this === obj); // true
    }
}
obj.method();

var obj = {
    method: function () {
        console.log(this === obj); // true
    }
}
obj.method();

二、功能域中的this

二、成效域中的this

  在浏览器中,功能域正是全局成效域,this
指的正是以此大局对象(就像是window):

  在浏览器中,作用域就是全局作用域,this
指的正是这几个大局对象(就好像window):

复制代码 代码如下:

复制代码 代码如下:

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

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

在Node.js中,你平凡都以在module中举办函数的。因而,顶尖作用域是个很尤其的模块效能域(module
scope):

在Node.js中,你习认为常都以在module中实行函数的。因此,超级效率域是个很尤其的模块功用域(module
scope):

复制代码 代码如下:

复制代码 代码如下:

// `global` (not `window`) refers to global object:
console.log(Math === global.Math); // true

// `global` (not `window`) refers to global object:
console.log(Math === global.Math); // true

// `this` doesn’t refer to the global object:
console.log(this !== global); // true
// `this` refers to a module’s exports:
console.log(this === module.exports); // true

// `this` doesn’t refer to the global object:
console.log(this !== global); // true
// `this` refers to a module’s exports:
console.log(this === module.exports); // true

3、eval()中的this

3、eval()中的this

  eval()能够被间接(通过调用那一个函数名’eval’)恐怕直接(通过别的办法调用,举例call())地调用。要领悟越多细节,请看这里。

  eval()能够被一贯(通过调用那么些函数名’eval’)恐怕直接(通过其余方法调用,比方call())地调用。要打听更加多细节,请看这里。

复制代码 代码如下:

复制代码 代码如下:

// Real functions
function sloppyFunc() {
    console.log(eval(‘this’) === window); // true
}
sloppyFunc();

// Real functions
function sloppyFunc() {
    console.log(eval(‘this’) === window); // true
}
sloppyFunc();

function strictFunc() {
    ‘use strict’;
    console.log(eval(‘this’) === undefined); // true
}
strictFunc();

function strictFunc() {
    ‘use strict’;
    console.log(eval(‘this’) === undefined); // true
}
strictFunc();

// Constructors
var savedThis;
function Constr() {
    savedThis = eval(‘this’);
}
var inst = new Constr();
console.log(savedThis === inst); // true

// Constructors
var savedThis;
function Constr() {
    savedThis = eval(‘this’);
}
var inst = new Constr();
console.log(savedThis === inst); // true

// Methods
var obj = {
    method: function () {
        console.log(eval(‘this’) === obj); // true
    }
}
obj.method();

// Methods
var obj = {
    method: function () {
        console.log(eval(‘this’) === obj); // true
    }
}
obj.method();

 4、与this有关的圈套

 四、与this有关的陷阱

  你要小心上面将介绍的三个和this
有关的骗局。要注意,在底下的事例中,使用Strict情势(strict
mode)都能狠抓代码的安全性。由于在实函数中,this
的值是undefined,当出现难点的时候,你会拿走警示。

  你要小心上边将介绍的三个和this
有关的圈套。要注意,在底下的事例中,使用Strict情势(strict
mode)都能拉长代码的安全性。由于在实函数中,this
的值是undefined,当出现难点的时候,你会获得警示。

  四.一  忘记行使new

  4.一  忘记行使new

  假令你不是使用new来调用构造器,那实在您正是在利用三个实函数。因而this就不会是您预期的值。在Sloppy形式中,this
指向的正是window 而你将会创立全局变量:

  尽管你不是应用new来调用构造器,那实在您正是在应用一个实函数。因而this就不会是你预期的值。在Sloppy方式中,this
指向的正是window 而你将会创造全局变量:

复制代码 代码如下:

复制代码 代码如下:

function Point(x, y) {
    this.x = x;
    this.y = y;
}
var p = Point(7, 5); // we forgot new!
console.log(p === undefined); // true

function Point(x, y) {
    this.x = x;
    this.y = y;
}
var p = Point(7, 5); // we forgot new!
console.log(p === undefined); // true

// Global variables have been created:
console.log(x); // 7
console.log(y); // 5

// Global variables have been created:
console.log(x); // 7
console.log(y); // 5

但是假如利用的是strict情势,那您要么会博得警示(this===undefined):

然而若是使用的是strict格局,那您要么会拿走警示(this===undefined):

复制代码 代码如下:

复制代码 代码如下:

function Point(x, y) {
    ‘use strict’;
    this.x = x;
    this.y = y;
}
var p = Point(7, 5);
// TypeError: Cannot set property ‘x’ of undefined

function Point(x, y) {
    ‘use strict’;
    this.x = x;
    this.y = y;
}
var p = Point(7, 5);
// TypeError: Cannot set property ‘x’ of undefined

肆.2 不恰本地行使办法

四.二 不恰本地动用方法

  若是您直接得到二个主意的值(不是调用它),你正是把这一个措施当做函数在用。当你要将四个艺术当做3个参数字传送入三个函数或许贰个调用方法中,你很或许会那样做。set提姆eout()和登记事件句柄(event
handlers)便是那种境况。我将会动用callIt()方法来效仿这么些地方:

  假若你一贯获得1个措施的值(不是调用它),你正是把那个办法当做函数在用。当您要将二个情势当做贰个参数字传送入三个函数也许一个调用方法中,你很可能会这么做。setTimeout()和注册事件句柄(event
handlers)就是那种气象。作者将会利用callIt()方法来模拟那个处境:

复制代码 代码如下:

复制代码 代码如下:

/** Similar to setTimeout() and setImmediate() */
function callIt(func) {
    func();
}

/** Similar to setTimeout() and setImmediate() */
function callIt(func) {
    func();
}

借让你是在Sloppy情势下将二个格局当做函数来调用,*this*本着的正是全局对象,所以事后创造的都会是大局的变量。

只要您是在Sloppy情势下将1个方法当做函数来调用,*this*针对的正是大局对象,所以随后创建的都会是全局的变量。

复制代码 代码如下:

复制代码 代码如下:

var counter = {
    count: 0,
    // Sloppy-mode method
    inc: function () {
        this.count++;
    }
}
callIt(counter.inc);

var counter = {
    count: 0,
    // Sloppy-mode method
    inc: function () {
        this.count++;
    }
}
callIt(counter.inc);

// Didn’t work:
console.log(counter.count); // 0

// Didn’t work:
console.log(counter.count); // 0

// Instead, a global variable has been created
// (NaN is result of applying ++ to undefined):
console.log(count);  // NaN

// Instead, a global variable has been created
// (NaN is result of applying ++ to undefined):
console.log(count);  // NaN

尽管您是在Strict模式下如此做的话,this是undefined的,你照旧得不到想要的结果,不过至少你会博得一句警告:

即使您是在Strict方式下那样做的话,this是undefined的,你要么得不到想要的结果,但是至少你会得到一句警告:

复制代码 代码如下:

复制代码 代码如下:

var counter = {
    count: 0,
    // Strict-mode method
    inc: function () {
        ‘use strict’;
        this.count++;
    }
}
callIt(counter.inc);

var counter = {
    count: 0,
    // Strict-mode method
    inc: function () {
        ‘use strict’;
        this.count++;
    }
}
callIt(counter.inc);

// TypeError: Cannot read property ‘count’ of undefined
console.log(counter.count);

// TypeError: Cannot read property ‘count’ of undefined
console.log(counter.count);

要想博得预期的结果,能够应用bind():

要想赚取预期的结果,能够运用bind():

复制代码 代码如下:

复制代码 代码如下:

var counter = {
    count: 0,
    inc: function () {
        this.count++;
    }
}
callIt(counter.inc.bind(counter));
// It worked!
console.log(counter.count); // 1

var counter = {
    count: 0,
    inc: function () {
        this.count++;
    }
}
callIt(counter.inc.bind(counter));
// It worked!
console.log(counter.count); // 1

bind()再次创下办了八个再而三能将this的值设置为counter 的函数。

bind()再创办了一个三番五次能将this的值设置为counter 的函数。

  4.3 隐藏this

  4.3 隐藏this

  当您在章程中选拔函数的时候,平日会忽视了函数是有和好的this
的。这么些this 又分别方法,因而你不可能把那五个this
混在一起使用。具体的请看下边那段代码:

  当您在点子中运用函数的时候,平日会忽略了函数是有温馨的this
的。这么些this 又差异方法,由此你不能够把那八个this
混在一同使用。具体的请看下边那段代码:

复制代码 代码如下:

复制代码 代码如下:

var obj = {
    name: ‘Jane’,
    friends: [ ‘Tarzan’, ‘Cheeta’ ],
    loop: function () {
        ‘use strict’;
        this.friends.forEach(
            function (friend) {
                console.log(this.name+’ knows ‘+friend);
            }
        );
    }
};
obj.loop();
// TypeError: Cannot read property ‘name’ of undefined

var obj = {
    name: ‘Jane’,
    friends: [ ‘Tarzan’, ‘Cheeta’ ],
    loop: function () {
        ‘use strict’;
        this.friends.forEach(
            function (friend) {
                console.log(this.name+’ knows ‘+friend);
            }
        );
    }
};
obj.loop();
// TypeError: Cannot read property ‘name’ of undefined

地点的例证里函数中的this.name 不能利用,因为函数的this
的值是undefined,那和办法loop()中的this
不雷同。上边提供了三种思路来缓慢解决这几个难题:

上边的事例里函数中的this.name 不能利用,因为函数的this
的值是undefined,这和章程loop()中的this
区别。上面提供了二种思路来化解这么些标题:

  一、that=this,将this 赋值到三个变量上,那样就把this
显性地展现出来了(除了that,self
也是个很普及的用于存放this的变量名),之后就接纳13分变量:

  一、that=this,将this 赋值到2个变量上,那样就把this
显性地球表面现出来了(除了that,self
也是个很普遍的用于存放this的变量名),之后就使用尤其变量:

www.bifa88.com,复制代码 代码如下:

复制代码 代码如下:

loop: function () {
    ‘use strict’;
    var that = this;
    this.friends.forEach(function (friend) {
        console.log(that.name+’ knows ‘+friend);
    });
}

loop: function () {
    ‘use strict’;
    var that = this;
    this.friends.forEach(function (friend) {
        console.log(that.name+’ knows ‘+friend);
    });
}

2、bind()。使用bind()来成立1个函数,这些函数的this
总是存有您想要传递的值(上边那一个事例中,方法的this):

二、bind()。使用bind()来成立一个函数,这几个函数的this
总是存有您想要传递的值(上面那几个事例中,方法的this):

复制代码 代码如下:

复制代码 代码如下:

loop: function () {
    ‘use strict’;
    this.friends.forEach(function (friend) {
        console.log(this.name+’ knows ‘+friend);
    }.bind(this));
}

loop: function () {
    ‘use strict’;
    this.friends.forEach(function (friend) {
        console.log(this.name+’ knows ‘+friend);
    }.bind(this));
}

3、用forEach的首个参数。forEach的第1个参数会被传播回调函数中,作为回调函数的this
来使用。

三、用forEach的第一个参数。forEach的第三个参数会被传播回调函数中,作为回调函数的this
来使用。

复制代码 代码如下:

复制代码 代码如下:

loop: function () {
    ‘use strict’;
    this.friends.forEach(function (friend) {
        console.log(this.name+’ knows ‘+friend);
    }, this);
}

loop: function () {
    ‘use strict’;
    this.friends.forEach(function (friend) {
        console.log(this.name+’ knows ‘+friend);
    }, this);
}

5、最棒执行

五、最佳试行

理论上,小编感到实函数并未属于自身的this,而上述的消除方案也是比照那几个观念的。ECMAScript
六是用箭头函数(arrow
function)来兑现这么些功能的,箭头函数正是未有团结的this
的函数。在如此的函数中您能够任由接纳this,也不用顾忌有未有隐式的存在。

反驳上,笔者感到实函数并不曾属于自身的this,而上述的化解方案也是比照那个观念的。ECMAScript
陆是用箭头函数(arrow
function)来落到实处这些功能的,箭头函数就是未有团结的this
的函数。在如此的函数中你可以不管选择this,也不用忧郁有没有隐式的留存。

复制代码 代码如下:

复制代码 代码如下:

loop: function () {
    ‘use strict’;
    // The parameter of forEach() is an arrow function
    this.friends.forEach(friend => {
        // `this` is loop’s `this`
        console.log(this.name+’ knows ‘+friend);
    });
}

loop: function () {
    ‘use strict’;
    // The parameter of forEach() is an arrow function
    this.friends.forEach(friend => {
        // `this` is loop’s `this`
        console.log(this.name+’ knows ‘+friend);
    });
}

自个儿不喜欢有些API把this 当狠抓函数的贰个附加参数:

笔者不希罕有个别API把this 当坚实函数的一个外加参数:

复制代码 代码如下:

复制代码 代码如下:

beforeEach(function () { 
    this.addMatchers({ 
        toBeInRange: function (start, end) { 
            …
        } 
    }); 
});

beforeEach(function () { 
    this.addMatchers({ 
        toBeInRange: function (start, end) { 
            …
        } 
    }); 
});

把1个隐性参数写成显性地规范传入,代码会显得越来越好精通,而且那样和箭头函数的渴求也很雷同:

把3个隐性参数写成显性地标准传入,代码会显得更加好掌握,而且那样和箭头函数的须求也很均等:

复制代码 代码如下:

复制代码 代码如下:

beforeEach(api => {
    api.addMatchers({
        toBeInRange(start, end) {
            …
        }
    });
});

beforeEach(api => {
    api.addMatchers({
        toBeInRange(start, end) {
            …
        }
    });
});

你也许感兴趣的稿子:

  • JAVASC昂科雷IPT THIS详解
    面向对象
  • javascript中的this详解
  • Javascript中this的用法详解
  • Javascript学习笔记之 函数篇(贰) : this
    的办事机制
  • javascript中的self和this用法小结
  • javascript面向对象之访问对象属性的二种方法分析
  • javascript面向对象之对象的深入驾驭
  • javascript面向对象连忙入门实例
  • 浅谈JavaScript完毕面向对象中的类
  • javascript
    面向对象封装与持续
  • javascript面向对象之this关键词用法分析

所在的地点来领会它,意况大概能够分为3种: 一、在函数中:this
平常是多少个含有的参数。 2、在函数外(一流效用域中):在浏…