走心大白话JavaScript教程(一)理解JS中this指向的小技巧

JS大法好,JS在手,天下我有,信JS,得永生。

这个系列的教程我一开始是写在github上的,
可是以为放到掘金来可让更多须要的人看到,
就搬到掘金专栏上啦,
若是以为本教程对你有帮助,请点这里去github上给我一颗Star~
教程目录也在github上哈~javascript

本着对技术负责的态度,任何纠正/疑问,尽管提出,我会及时修正/回答。

必定要把每一个例子代码都拷贝到你的运行环境中边看结果边理解,否则学习效果减半,或者没效果。

闲话说太多了~下面开始第一篇:java

理解JS中this指向的小技巧

在看他人写的js文件时,会看到许多this,
对this不熟悉的人很容易蒙圈,这里就说明如何用最简单的方法去找this指向谁。git

切记!这里说的找“点”大法中的“.”,都是在调用的语句里找,本教程的全局对象为window!


一、找“点”大法:你找不到“.”的函数调用,this指向通常是window:

声明
function foo(){
  console.log(this)
}复制代码
调用
foo();    //本身去运行代码看this指向谁
//脑补:
window.foo();   //本身去运行代码看this指向谁复制代码
解读
不用怀疑,也不用犹豫,找不到任何“.”,this指向window。
之后见到直接调用的foo,自动脑补成window.foo(),由于在这种状况下,这两种写法是同样的。复制代码
㈠当函数/匿名函数做为参数时,你是找不到“.”的,这种状况下,函数内部的this指向window。
声明&调用
function foo(callback){
    callback(); //调用其实在这里,你是找不到“.”的
}
foo(function(){
    console.log(this);  //本身去运行代码看this指向谁
})复制代码
解读
这个例子就是,匿名函数内部打印了this,它做为参数,内部的this指向window复制代码


二、找“点”大法:有“.”的函数调用,this指向通常是最后一个“.”左侧的那个对象:

2-一、调用语句里只能找到一个“.”:
声明
var bar = {name:'我是bar'};
bar.foo = function(){
  console.log(this)
};复制代码
调用
bar.foo();  //本身去运行代码看this指向谁复制代码
解读
这个例子,咱们找到了“.”的存在,“.”左侧是bar,指向是bar。复制代码
2-二、调用语句里能找到多个“.”:
声明
var obj = {name:'我是obj'};
obj.bar = {name:'我是bar'};
obj.bar.foo = function(){
  console.log(this)
};复制代码
调用
obj.bar.foo();  //本身去运行代码看this指向谁复制代码
解读
这个例子,咱们找到了俩“.”,最后一个“.”左侧的对象是bar,那么this指向就是bar。复制代码
㈡若是发现你找到的“.”左侧是prototype,那么再往左找一个“.”,这个“.”左侧的对象是this指向。原理在不得不提的原型/原型链中给出。


三、面向对象中的this:

对面向对象不够了解的同窗,请尽可能读懂不得不提的原型/原型链

阅读本文,就先专一于找this指向吧!github

声明
function Foo(){
    this.name = 'hahaha'
    console.log(this);
}
Foo.prototype.bar = function(){
    console.log(this);
}
Foo.prototype.funcWithParam = function(fn){
    fn();
}复制代码
调用
Foo();  //本身去运行代码看this指向谁

Foo.prototype.bar();  //本身去运行代码看this指向谁

var foo = new Foo(); //本身去运行代码看this指向谁

foo.name = '我是foo';

foo.bar(); //本身去运行代码看this指向谁

foo.funcWithParam(function(){
    console.log(this);  //本身去运行代码看this指向谁
});复制代码
解读
当Foo()时,Foo被当作[普通函数],那么遵循找“点”大法,Foo内部的this是指向window的;

当Foo.prototype.bar()时,Foo仍是被当作[普通函数],遵循找“点”大法,按照2-2,发现找到了prototype,转而遵循㈡,再向左找,发现this指向Foo;

当new Foo()时,Foo做为[构造函数]被实例化,Foo内部的this指向实例化后的Foo,也就是我声明的foo;

当foo.bar时,遵循找“点”大法,按照2-1,发现this指向foo;

当foo.funcWithParam(匿名函数)时,匿名函数前没有“.”,匿名函数做为参数,因此遵循㈠,发现其内部this指向window复制代码


四、call和apply会改变this指向,在巧妙理解call、apply单独详解。


小结:

  • 找不到“.”的函数调用,其内部的this通常指向window象;
  • 找获得“.”的函数调用,其内部的this通常指向最后一个“.”左侧的那个对象,若是左侧是prototype,再向左找一个;
  • 明确区分函数是[构造函数]仍是[普通函数],[构造函数]内的this指向实例化后的对象;
  • 函数做为参数传递,被调用时其内部的this通常指向window。
  • call和apply会改变this指向,参阅巧妙理解call、apply
  • ES6/7的箭头函数也会影响this指向,这个很简单,我就很少讲啦~

一句话来讲,就是“谁调的我(普通函数),我内部的this就指向谁;new我一下(构造函数),我内部的this就指向个人实例化”

PS:
欢迎转载,须要注明原址。
教程之间紧密联系,不懂的地方,请好好看下全系列教程目录
有没有你不懂的那个关键字在里面。
若是帮到你,别忘了给我一颗Star~
app

相关文章
相关标签/搜索