谈"this"

  首先,很多人对this有两个误解

  1.this指向的是当前函数本身

  什么意思呢,下面看一段代码。

1 function func(){
 2     this.a ++;
 3 }
 4
 5 var a = 0;
 6 func.a = 0;
 7
 8 for(let i = 0; i < 5; i++){
 9     func();
10 }
11
12 console.log(a);  //->5
13 console.log(func.a);//->0

    发现问题了,因为函数本身也是一个对象,如果this指向的是当前函数本身,那么在调用func函数5次后,func.a应该输出的是5,但是程序结果输出的是0,但是全局定义的a变量输出了结果5,显然在这里函数中this指向的不是函数本身,而指向了全局对象.

    这是为什么呢?接着往下看。

   

  2.this指向的是当前函数的作用域

  先看一段代码:

function foo(){
    var a = 0;
    this.bar();
}

function bar(){
    console.log(this.a);
}

foo();//->undefined

  这段代码在按照“this指向的是当前函数的作用域”这样的理解下,在理想的执行状态下是这样子的:

//foo();

function foo(){
    var a = 0;
    console.log(a);
}

  因为按照上文理解,this指向的是当前的函数作用域,所以这段代码能够执行成功是有问题的,如果this指向的是当前的函数作用域,foo函数的词法作用域中并没有一个标识符为bar的函数;

  在严格模式下,这段代码是无法执行的(报错)。

  

  

  this到底是一个什么样的机制呢?那么这里下一个定义:this的指向是取决于函数调用的方式,跟函数怎么写没有半毛钱关系。this的指向并没有在编写代码的时候就绑定了,而发生在函数的调用时。

  当一个函数被调用时,会创建一个活动记录(执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this就是这个记录的一个属性,会在函数执行的过程中用到。

  

函数调用位置的追踪:

function baz(){
    //当前的调用栈是:baz
    //因此,当前调用位置是全局作用域

    console.log("baz");
    bar(); // <-- bar的调用位置
}

function bar(){
    //当前调用栈是:baz -> bar
    //因此,当前调用位置在baz中
    console.log("bar");
    foo();  // <-- foo的调用位置
}

function foo(){
    //当前的调用栈是:baz -> bar -> foo
    //因此,当前的调用位置在bar中
    console.log("foo");
}

baz();  //<-- baz的调用位置

既然this的绑定取决于函数的调用方式,那么this存在下面这四种绑定规则:

  • 默认绑定
  • 隐式绑定
  • 显示绑定
  • new绑定

默认绑定:简单地来讲,默认绑定就是单独的,没有任何修饰符的函数调用,就像这样。

foo();

这时,this指向全局对象,下面给这个函数加上this来试一试。

function foo(){
    console.log(this.num);
}

var num = 6;

foo(); //->6

但是,只有在非严格模式下,this在默认绑定下才能绑定到全局对象上;如果在严格模式下,this会绑定到undefined。

记住了,就光写一个光秃秃的函数调用,就是默认绑定,这时this指向的是全局对象(在非严格模式下)。

隐式绑定:又是简单地来讲,隐式绑定就是当这个函数作为某个对象的方法被调用时,this就会指向这个对象。

obj.foo();

考虑一下调用的位置是否有上下文对象,就是说这个函数是否被某个对象拥有或包含。

function foo(){
    console.log(this.a);
}

var obj = {
    a : 2,
    foo : foo
};

obj.foo(); // -> 2 这时foo函数的this指向obj这个对象

因为这时this函数指向的就是包含它的obj对象,所以此时this.a === obj.a

这就叫做隐式绑定,不过隐式绑定有一个问题,最常见的问题就是被隐式绑定的函数会丢失绑定对象,怎么回事呢,来看一下下面的代码:

function foo(){
    console.log( this.a );
}

var obj = {
    a : 2,
    foo : foo
};

var bar = obj.foo;

var a = "global";  //a是全局对象的属性

bar();  // -> "global"

看到没?本来foo应该指向obj来着,现在指向了全局对象,是怎么回事呢?那是因为obj的方法foo作为一个单独的函数被赋值给了bar,bar就成了foo函数的别名,输出一下bar,看看里面是什么:

这里可以看到,bar的内容是foo函数的函数体,所以这里调用bar,与foo()语句等价,使用了默认绑定,this指向全局对象,所以才会输出"global",在编程中,要注意这个细节。

显式绑定:显式绑定说白了就是函数使用call方法或apply显式地指定了this的指向。

例如:

function foo(){
    console.log( this.a );
}

var obj = {
    a : 2
};

foo.call( obj );  //->2

说到了call和apply,他俩也没啥区别,只是调用时写法有点不一样:

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2]);

call的函数参数一直写,中间用逗号隔开,apply的函数参数以数组形式给出。

new绑定:这个就不用说了,在用new调用函数时,函数内的this指向当前对象。

在JavaScript中,没有明显的标识符什么的说明构造函数是构造函数,实际上,Javascript不存在构造函数,只有被“构造调用”的普通函数。new关键字将一个普通函数“构造调用”,并且将这个普通函数的this与创建的对象相关联。

function Person( name, sex ){
    this.name = name;
    this.sex = sex;
}

// -> Person的this现在指向xiaoming
var xiaoming = new Person("小明","男");

那么基本的this指向问题就这么简单地说完了,总结一下,this的指向其实跟函数如何编写没有什么关系,只跟函数调用的方式有关系。希望这篇文章可以帮到大家更好地理解this的问题,如果有补充或者疑问,请在评论区留言,谢谢!

(0)

相关推荐

  • Angular zone学习笔记

    https://blog.thoughtram.io/angular/2016/01/22/understanding-zones.html 假设有这三个函数: foo();bar();baz();f ...

  • ES6中的函数(函数参数、默认值、箭头函数)

    一.函数参数的解构赋值 function foo([a,b]) { console.log(a+b); // 3 } foo([1,2]); function bar({c,d}) { console ...

  • this 的值到底是什么?一次说清楚

    你可能遇到过这样的 JS 面试题: var obj = { foo: function(){ console.log(this) }}var bar = obj.fooobj.foo() // 打印出 ...

  • 姚策养母谈错换人生案伤害:现已家破人亡,起诉医院只为真相

    2021年05月07日 21:59:00 来源:正面FACE 5月8日,姚策养母许敏起诉医院一案将在河南开封开庭,近日,许敏告诉凤凰网正面FACE ,在谈到医院错换对他们家的影响时,她说道:" ...

  • 浅谈乡村治理模式发生了哪些变化?

    随着乡村现代化的发展,越来越多的乡村走上了建设数字乡村的道路,从传统的乡村治理到使用互联网数字化治理的模式,乡村的风貌和农民的生活也发生了巨大的变化,接下来就让我们一起来了解一下乡村治理模式到底发生了 ...

  • 汽车是怎么开发出来的?浅谈汽车开发流程

    许良  汽车话题下的优秀答主你知道汽车是怎么开发出来的吗?你的脑海中很可能浮现出来这样一个画面:一个非常有艺术气息的设计师,在草图上帅气的描绘着看起来非常犀利的线条.对,但不全对.对于汽车工程师的我而 ...

  • 简谈贵州的自然环境和自然资源

    一.贵州的自然环境 地貌: ①贵州的地貌特征表现为典型的喀斯特地貌.地上广泛分布着石沟.峰林.瀑布.喀斯特湖等千奇百怪的喀斯特地貌.地下发育了溶洞.暗河.石钟乳.石钟柱等喀斯特景观. ②贵州的地貌深受 ...

  • 为什么一个人明明单身,却长期不谈恋爱

    为什么一个人明明单身,却长期不谈恋爱

  • 浅谈办公室装修的发展前景和趋势

    未来办公室装修的发展趋势会是怎样的?这是这个行业未来前景的重要话题.在这样一个新时代里,所有的事物都会以最新颖的方式出发.科技的发展也让每个行业都转遍了方向,同时对行业的要求和品质也有了更高的要求. ...

  • 健康大家谈 | 家有过敏娃,家长怎么办

    到了春天,过敏的宝宝似乎多了起来.鼻子痒.流清涕.打喷嚏.皮肤瘙痒.反复咳喘--孩子的这些问题让家长十分头痛.着急的家长带着孩子去医院,医生都说孩子过敏了.还有一些家长"久病成医" ...

  • 谈一谈古人对于癫痫的认识

    中医传统上把癫痫称作痫证或痫病,癫痫是后来的叫法.在民间,人们习惯把癫痫病叫"羊角风"."羊癫风"."猪婆风"等等早期医书上,医家多把癫.狂 ...

  • 屈杰:从《本草纲目》谈桂枝汤

    导读: 临证心得|漫谈桂枝汤 从<本草纲目>谈桂枝汤 李时珍<本草纲目>搜罗万象,是举世公认的医药百科全书.本人对<本草纲目>情有独钟.希望通过研读桂枝汤单味药物的 ...

  • 大德中医谈癫痫病的中医疾病发病机理分析

    ​癫痫疾病的发生因素很复杂,古人在几千年以前就开始研究和关注这一类疾病 .其中最重要的一种发病因素就是胎病,传统医书上把它称作"胎痫",意为胎里带来的. 譬如胎儿大脑发育不全,脏腑 ...