热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《YouDon'tKnowJS》浏览明白——this

1.this的降生假定我们有一个speak函数,经由历程this的运转机制,当运用差别的要领挪用它时,我们能够天真的输出差别的name。varme{name:me};functio

1. this的降生

假定我们有一个speak函数,经由历程this的运转机制,当运用差别的要领挪用它时,我们能够天真的输出差别的name。

var me = {name: "me"};
function speak() {
console.log(this.name);
}
speak.call(me) //me

然则假如没有this, 这时刻我们须要显现的通报上下文给该函数。这时刻必需硬性的指定上下文,代码的复杂度增添,天真性也短缺。

function speak(context) {
console.log(context.name);
}

2. this的运转机制

2.1 运转道理

When a function is invoked, an activation record, otherwise known as an execution context, is created. This record contains information about where the function was called from (the call-stack), how the function was invoked, what parameters were passed, etc. One of the properties of this record is the this reference which will be used for the duration of that function’s execution.

当函数被挪用时, 函数会建立一个activation object(实行上下文), 这个对象包含了函数在那里被挪用(挪用栈),函数的挪用体式格局,传入的参数,以及this值。

因而,我们能够看到,this值是在函数挪用时赋值的,而不是在声明的时刻。是动态的。

2.2 运转划定规矩

依据this的运作道理,我们能够看到,this的值和挪用栈(经由历程哪些函数的挪用运转到挪用当前函数的历程)以及怎样被挪用有关。

2.2.1 Default Binding(默许绑定)

当函数是被自力挪用时,this值在非严厉形式下为全局对象, 严厉形式下为undefined.

var a = 1;
function foo() {
var a = 2;
console.log(this.a);
}
function bar() {
debuuger;
foo();
}
bar();

翻开chrome devtool能够看到,在挪用foo时,函数的挪用栈为bar -> foo,挪用体式格局是自力挪用,且是在非严厉形式下,此时this值指向window,输出1。

《《You Don't Know JS》浏览明白——this》

2.2.2 Implicit Binding(隐式绑定)

var = 1;
function foo() {
debugger;
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
}
obj.foo(); //2

此时,挪用foo时,函数前加上了对obj这个对象的援用,输出obj.a

因而,假如有上下文对象援用了函数,隐式绑定划定规矩会指定this值为该援用对象。

《《You Don't Know JS》浏览明白——this》

然则我们再看看下面这类状况。要注重的是,bar的值是对函数foo的援用,因而此时foo的挪用并没有上下文对象的援用,因而运用的是default binding, 输出1。要注重这类赋值的状况。

var a = 1;
function foo() {
debugger;
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
}
var bar = obj.foo;
bar(); //1

2.2.3 Explicit Binding(显式绑定)

上面两种状况,要么this值为全局对象(非严厉形式),要么经由历程对象要领挪用,this指向挪用的对象。
那我想不经由历程对象挪用,而是自力挪用时又能指定this值为某个对象呢?这时刻,call,apply就降生了。它的第一个参数是this值,协助我们邃晓指定函数挪用时this的值。

var a = 1;
function foo() {
debugger;
console.log(this.a);
}
var obj = {
a: 2
}
foo.call(obj); //2

《《You Don't Know JS》浏览明白——this》

经由历程call, apply,我们能够在挪用时邃晓指定this值。另有一种状况是,有时刻我们愿望this值绑定在我们给定的对象上,而函数只须要吸收一些参数。特别是在第三方库中,它会供应一种要领,吸收要领须要的参数,然则不愿望你不测的修正了要领的this值,这时刻它可能会采纳bind这类硬性绑定的要领邃晓的指出this值。

在ES5中供应了Function.prototype.bind,它的运用场景就是协助你predicable的绑定this值。经常使用的运用场景为包裹函数、事宜绑定函数、setTimeout中绑定this

//包裹函数,用来吸收参数
function multiple(num) {
console.log(this.pen, num);
return this.pen * num;
}
var priceMapping = {
pen: 10
}
function calTotalPrices() {
return multiple.apply(priceMapping, arguments);
}
var total = calTotalPrices(3);
console.log(total); //30

//事宜绑定
var states = {
clickCount: 0
}
function clickHandler() {
this.clickCount++;
console.log(this.clickCount);
}
button.addEventListener('click', clickHandler.bind(states));

注重:当运用显现绑定时,假如第一个参数是null, undefined,则运用默许绑定划定规矩。为防止传入null, undefined时毛病的改变了全局值,最好建立一个空对象替代null, undefined

var ø = Object.create(null);
foo.call(ø);

2.2.4 new Binding(new绑定)

邃晓new的运作道理:

  1. 建立一个新对象;

  2. 对象链接到[[prototype]]上;

  3. this绑定到这个新对象上;

  4. 有显式的return,返回return,不然返回这个新对象。

2.2.5 优先级

new > 显现绑定(call,apply,bind) > 隐式绑定(要领挪用) > 默许绑定(自力函数挪用)

function foo(sth) {
this.b = sth;
console.log("a:", this.a, "b:", this.b);
}
var a = "window";
var obj1 = {
a: "obj1",
foo: foo,
}
var obj2 = {
a: "obj2",
foo: foo,
}
obj1.foo("obj1"); //a: obj1 b: obj1
obj1.foo.call(obj2, "obj2"); //a: obj2 b: obj2; 显现 > 隐式
var bar = foo.bind(obj1);
new bar("new"); //new > 显现

4. 箭头函数

箭头函数中的this并不适用于以上四种划定规矩。由于这里的this不是运用的传统this机制,而是运用的词法作用域,依据外层的作用域来决议this。运用机制不一样,该this也不能经由历程显现绑定来修正。

5. 总结

下一次再看到this的时刻,我们问本身两个题目:

  1. where to call: 函数的挪用位置是?

  2. how to call: 函数的挪用要领是?运用的划定规矩是?

  3. 运用划定规矩4条(按优先级排序):

    • new (新建立的对象)

    • 显式绑定 (绑定到指定对象,call, apply, bind:可展望的this);

    • 隐式绑定 (挪用的上下文对象,注重间接援用的毛病);

    • 默许绑定 (全局对象或undefined注重函数体是不是为严厉形式);


推荐阅读
author-avatar
Json
技术QQ交流群:294088839.
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有