├── pics
├── timg.jpg
└── top.jpg
├── README.md
├── this
└── README.md
├── proto
└── README.MD
└── call-apply
└── README.MD
/pics/timg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TerryBeanX2/Dive-Into-JS/HEAD/pics/timg.jpg
--------------------------------------------------------------------------------
/pics/top.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TerryBeanX2/Dive-Into-JS/HEAD/pics/top.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 走心的一系列JS基础>进阶的大白话教程
2 |
3 |
4 |
5 | #### JS大法好,JS在手,天下我有,信JS,得永生。
6 | 想必每一个前端攻城狮都知道,区分能力的最重要的指标就是对JavaScript的掌握程度,
7 | 在热门框架满天飞,自动化越来越被推崇的今天,
8 | 好多开发者都失其本心,盲目去追求技术的广度而忽略本身羸弱的JS功底,
9 | 殊不知你若是对JS掌握到位,任何框架神马的新技术,都是信手拈来的。
10 |
11 | 通过长期的浸淫于网上的JS领域,我发现除了少数布道者能讲得通俗易懂(比如阮一峰老师、廖雪峰老师),
12 | 而其他大多数的进阶教程,看似美食但难以下咽,
13 | 原因就是很多教程都忽略了“马上要懂而又没懂就差那么一丢丢”的开发者的主观感受,
14 | 要么就是一股脑塞给你一堆知识点,要么就是有点艰涩,
15 | 导致学习这些教程后,知识粘度不够,马上就忘了,或者压根就懒得理解。
16 |
17 | 而我开这一解读栏的目的,就是在力所能及的知识范围内,
18 | 帮助那些“马上要懂而又没懂就差那么一丢丢”的开发者们,在某些个具体化的知识点上(仅仅是某些个),
19 | 用最简单的白话解读出来,包括我自己的理解小技巧。
20 | 当然这只是我的理想化,也许教程写出来很烂,甚至偏离了初衷,但只要帮助了哪怕只有一个人,这个教程就不白写。
21 |
22 | #### 本着对技术负责的态度,任何纠正/疑问,请在[issues](https://github.com/TerryBeanX2/Dive-Into-JS/issues)里提出,我会及时修正/回答。
23 | #### 一定要把每个例子代码都拷贝到你的运行环境中边看结果边理解,不然学习效果减半,或者没效果。
24 |
25 | [1、理解this指向的小技巧](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/this)
26 | [2、巧妙理解call、apply](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/call-apply)
27 | [3、不得不提的原型/原型链](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/proto)
28 | 4、占位,视情况填坑
29 | +、...
30 |
31 | #### 教程之间紧密联系,不懂得地方不要失去耐心,来回多看看。
32 | #### 如果帮到你,给我一个Star吧,我会继续努力写下去~
33 |
--------------------------------------------------------------------------------
/this/README.md:
--------------------------------------------------------------------------------
1 | # 理解JS中this指向的小技巧
2 |
3 | 在看他人写的js文件时,会看到许多this,对this不熟悉的人很容易蒙圈,这里就说明如何用最简单的方法去找this指向谁。
4 |
5 | #### 切记!这里说的找“点”大法中的“.”,都是在调用的语句里找,本教程的全局对象为window!
6 |
7 | ## 1、找“点”大法:你找不到“.”的函数调用,this指向一般是window:
8 |
9 | ###### 声明
10 | ```javascript
11 | function foo(){
12 | console.log(this)
13 | }
14 | ```
15 | ###### 调用
16 | ```javascript
17 | foo(); //自己去运行代码看this指向谁
18 | //脑补:
19 | window.foo(); //自己去运行代码看this指向谁
20 | ```
21 | ###### 解读
22 |
23 | 不用怀疑,也不用犹豫,找不到任何“.”,this指向window。
24 | 以后见到直接调用的foo,自动脑补成window.foo(),因为在这种情况下,这两种写法是一样的。
25 |
26 | ##### ㈠当函数/匿名函数作为参数时,你是找不到“.”的,这种情况下,函数内部的this指向window。
27 | ###### 声明&调用
28 | ```javascript
29 | function foo(callback){
30 | callback(); //调用其实在这里,你是找不到“.”的
31 | }
32 | foo(function(){
33 | console.log(this); //自己去运行代码看this指向谁
34 | })
35 | ```
36 | ###### 解读
37 |
38 | 这个例子就是,匿名函数内部打印了this,它作为参数,内部的this指向window。
39 |
40 | ## 2、找“点”大法:有“.”的函数调用,this指向一般是最后一个“.”左侧的那个对象:
41 | ##### 2-1、调用语句里只能找到一个“.”:
42 |
43 | ###### 声明
44 | ```javascript
45 | var bar = {name:'我是bar'};
46 | bar.foo = function(){
47 | console.log(this)
48 | };
49 | ```
50 | ###### 调用
51 | ```javascript
52 | bar.foo(); //自己去运行代码看this指向谁
53 | ```
54 | ###### 解读
55 |
56 | 这个例子,我们找到了“.”的存在,“.”左侧是bar,指向是bar。
57 |
58 | ##### 2-2、调用语句里能找到多个“.”:
59 |
60 | ###### 声明
61 | ```javascript
62 | var obj = {name:'我是obj'};
63 | obj.bar = {name:'我是bar'};
64 | obj.bar.foo = function(){
65 | console.log(this)
66 | };
67 |
68 | ```
69 | ###### 调用
70 | ```javascript
71 | obj.bar.foo(); //自己去运行代码看this指向谁
72 | ```
73 | ###### 解读
74 |
75 | 这个例子,我们找到了俩“.”,最后一个“.”左侧的对象是bar,那么this指向就是bar。
76 |
77 | ##### ㈡如果发现你找到的“.”左侧是prototype,那么再往左找一个“.”,这个“.”左侧的对象是this指向。原理在[不得不提的原型/原型链](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/proto)中给出。
78 |
79 |
80 | ## 3、面向对象中的this:
81 | 对面向对象不够了解的同学,请尽量读懂[不得不提的原型/原型链](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/proto)
82 | 阅读本文,就先专注于找this指向吧!
83 |
84 | ###### 声明
85 | ```javascript
86 | function Foo(){
87 | this.name = 'hahaha'
88 | console.log(this);
89 | }
90 | Foo.prototype.bar = function(){
91 | console.log(this);
92 | }
93 | Foo.prototype.funcWithParam = function(fn){
94 | fn();
95 | }
96 | ```
97 | ###### 调用
98 | ```javascript
99 | Foo(); //自己去运行代码看this指向谁
100 |
101 | Foo.prototype.bar(); //自己去运行代码看this指向谁
102 |
103 | var foo = new Foo(); //自己去运行代码看this指向谁
104 |
105 | foo.name = '我是foo';
106 |
107 | foo.bar(); //自己去运行代码看this指向谁
108 |
109 | foo.funcWithParam(function(){
110 | console.log(this); //自己去运行代码看this指向谁
111 | });
112 |
113 | ```
114 | ###### 解读
115 |
116 | 当Foo()时,Foo被当做[普通函数],那么遵循找“点”大法,Foo内部的this是指向window的;
117 |
118 | 当Foo.prototype.bar()时,Foo还是被当做[普通函数],遵循找“点”大法,按照2-2,发现找到了prototype,转而遵循㈡,再向左找,发现this指向Foo;
119 |
120 | 当new Foo()时,Foo作为[构造函数]被实例化,Foo内部的this指向实例化后的Foo,也就是我声明的foo;
121 |
122 | 当foo.bar时,遵循找“点”大法,按照2-1,发现this指向foo;
123 |
124 | 当foo.funcWithParam(匿名函数)时,匿名函数前没有“.”,匿名函数作为参数,所以遵循㈠,发现其内部this指向window;
125 |
126 |
127 |
128 | ## 4、call和apply会改变this指向,在[巧妙理解call、apply](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/call-apply)单独详解。
129 |
130 |
131 |
132 | ## 小结:
133 |
134 | * 找不到“.”的函数调用,其内部的this一般指向window象;
135 | * 找得到“.”的函数调用,其内部的this一般指向最后一个“.”左侧的那个对象,如果左侧是prototype,再向左找一个;
136 | * 明确区分函数是[构造函数]还是[普通函数],[构造函数]内的this指向实例化后的对象;
137 | * 函数作为参数传递,被调用时其内部的this一般指向window。
138 | * call和apply会改变this指向,参阅[巧妙理解call、apply](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/call-apply)。
139 | * ES6/7的箭头函数也会影响this指向,这个很简单,我就不多讲啦~
140 |
141 | #### 一句话来说,就是“谁调的我(普通函数),我内部的this就指向谁;new我一下(构造函数),我内部的this就指向我的实例化”
142 |
143 |
144 | 欢迎转载,需要注明原址。如果帮到你,希望得到你的Star~
145 | PS:教程之间紧密联系,不懂的地方,请好好看下[目录](https://github.com/TerryBeanX2/Dive-Into-JS#提供给有一定js基础开发者进阶知识点大白话解读),有没有你不懂的那个关键字在里面。
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/proto/README.MD:
--------------------------------------------------------------------------------
1 | # 不得不说的原型与原型链:prototype与__proto__
2 |
3 | ## 1、纸面意思
4 | 啥是原型,啥是原型链?
5 | 原型:一个属性,属性名叫prototype,只有构造函数有,比如Foo.prototype;
6 | 原型链:一个属性,属性名叫__proto__,万物皆有,链状相连,最后归宗到Object.prototype上,Object.prototype的__proto__值为null;
7 |
8 | ## 2、尝试理解一下这两个点,记住一定配合控制台去打印。
9 | * 访问一个实例的属性,JS会先在实例内部寻找,找不到的话,沿着原型链继续找下去。
10 | ```javascript
11 | function Foo(){this.name='我是构造函数Foo'} //一个构造函数Foo
12 |
13 | var foo = new Foo(); //通过new Foo(),得到实例化的foo
14 |
15 | console.log(foo.bar); //访问foo的bar属性,控制台打印一下,得到undefined
16 |
17 | Foo.prototype.bar = '我是bar属性,在Foo.prototype(Foo的原型)里'; //给Foo.prototype添加bar属性
18 |
19 | console.log(foo.bar); //再次访问foo的bar属性,控制台打印一下看看。结果验证了"沿着原型链找下去"这句话。
20 |
21 | Object.prototype.examAttr = '我是examAttr属性,在Object.prototype(Object的原型)里'; //给Object.prototype添加examAttr属性
22 |
23 | console.log(foo.examAttr); //访问foo的examAttr属性,控制台打印一下看看。结果验证了"一直找到Object.prototype"这句话。
24 | ```
25 |
26 | 配合之前写的纸面意思,回味一下上面的代码。
27 | * 每个构造函数都有一个原型,这个原型的constructor属性就是这个构造函数。
28 | ```javascript
29 | function Foo(){this.name='我是构造函数Foo'} //一个构造函数Foo
30 |
31 | console.log(Foo.prototype); //打印结果可以看到一个Object对象,即Foo的原型,里面有一个constructor属性,属性值即为Foo函数。
32 |
33 | var foo = new Foo(); //实例化
34 |
35 | console.log(foo.constructor); //foo中没有constructor属性,沿着原型链找到Foo的原型(即上面打印的结果),得到Foo原型的constructor属性值,即Foo函数。
36 | ```
37 |
38 | 以上代码解释了为什么通过查看实例的constructor属性可以得到实例的构造函数。重点在于“沿着原型链找”。
39 | ## 3、从老生常谈的JS实现new运算符过程来剖析
40 | ```javascript
41 | //写一个构造函数,定义其prototype
42 | function Foo(name) {
43 | this.name = name;
44 | }
45 | Foo.prototype = {
46 | constructor:Foo, //由于重新定义了prototype,咱们把constructor属性补上。
47 | say: function () {
48 | console.log('My name is ' + this.name);
49 | }
50 | };
51 | //JS实现new的方法generate
52 | function generate(Fun,arguments) {
53 | var foo = {}; //新建一个空对象
54 | Fun.apply(foo, arguments); //利用apply改变this指向,现在运行Fun时,内部this指向foo空对象,那么给this.name赋值就变成了给foo.name赋值。
55 | foo.__proto__ = Fun.prototype; //把foo的__proto__属性指向Fun.prototype。
56 | return foo;
57 | }
58 | //执行generate,模拟new
59 | var foo = generate(Foo,["Terry"]); //相当于 var foo = new Foo("Terry")
60 | //验证实例方法
61 | foo.say();
62 | //查看foo的构造函数
63 | console.log(foo.constructor);
64 | ```
65 | #### 上面的代码完全实现了new运算符的逻辑,所以说,new运算符就是上面这段代码的语法糖而已。
66 |
67 | 下面这张图想必很多人都很熟悉,我截取了小上半部分,
68 | 不要考虑看不见的导线,只关心f1、Foo、Foo.prototype三者的关系就够了。
69 | 配合下面这张图,再回头看一下JS实现new的过程:
70 |
71 |
72 | ###### 理不清没关系,我们来解析一下:
73 |
74 | 图中表示,f1由new Foo而来,而f1的__proto__连接着Foo.prototype,
75 | 这说明Foo的实例f1的__proto__(原型链)是指向Foo.prototype(原型)的,
76 | 你再回头去看我们用JS实现new所封装的方法generate,有这么一句:
77 | foo.__proto__ = Fun.prototype;
78 | 那不就是手动把foo(图中的f1)的原型链指向Fun(图中的Foo)的原型吗!
79 |
80 | ## 4、ES5面向对象中常用的混合模式
81 |
82 | 在封装代码/插件的时候,使用面向对象的混合模式来写,代码结构是这样的:
83 |
84 | ```javascript
85 | function MyPlugin(name){
86 | this.name = name; //每个实例都不一样的属性,写在构造函数里。
87 | }
88 | MyPlugin.prototype = {
89 | publicFun:function(){
90 | console.log('我是公共方法,所有实例共用'); //每个实例都调用一样逻辑的代码,封装成方法写进构造函数的原型里
91 | console.log(this.name+'使用了插件');
92 | }
93 | }
94 | //使用插件
95 | var myPlugin = new MyPlugin('小明');
96 | myPlugin.publicFun(); //实例并没有publicFun方法,但是JS从myPlugun.__proto__中找到了public。
97 | ```
98 |
99 | 通过找“点”大法(前面教程有说过),可以发现publicFun内部的this指向myPlugin,
100 | 也就验证了为什么[1、理解this指向的小技巧](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/this)中小结里的第三点:
101 | “明确区分函数是[构造函数]还是[普通函数],[构造函数]内的this指向实例化后的对象;”
102 | ###### 这回知道为什么插件可以这么写,并且实例化后的插件可以直接调用写在prototype里的方法了吧?
103 |
104 | ## 小结
105 | * 关于原型与原型链,没有什么“一句话来说”,仔细通读这篇教程吧,尤其是那张图。
106 |
107 | 欢迎转载,需要注明原址。如果帮到你,希望得到你的Star~
108 | PS:教程之间紧密联系,不懂的地方,请好好看下[目录](https://github.com/TerryBeanX2/Dive-Into-JS#提供给有一定js基础开发者进阶知识点大白话解读),有没有你不懂的那个关键字在里面。
109 |
110 |
--------------------------------------------------------------------------------
/call-apply/README.MD:
--------------------------------------------------------------------------------
1 | # 巧妙理解call和apply
2 | 想当年我还是个小白的时候,看到call和apply,那都是一脸懵逼啊!
3 | 再加上参数内部this,arguments什么的,虐的我不要不要的,一度产生厌学心理。
4 | 的确,这俩方法对初学者不够友好...
5 |
6 | 但是!作为半个老鸟,现在看到call啊什么apply啊什么的,也就微微一笑了。
7 | 想当初茅塞顿开的时候,那心里叫一个痛快,现在就把开窍的过程分享出来。
8 |
9 | ## 1、call和apply的区别
10 | 先说一下call和apply的区别,你在完全不懂俩函数是干嘛的情况下,你只要记住:
11 | call和apply的功能是完全一样的,只是第二个参数不一样;
12 | call可以接收无限多个参数,apply只接收俩参数,并且第二个参数只能是数组。
13 | “而它们同样的第一个参数,就是新的this指向!”你先不用管引号里的话说明了什么,脑子里默记下这句话就行。
14 | 好了,现在,不要多想,往下看。
15 |
16 |
17 | ## 2、call、apply会改变this指向
18 |
19 | 我在实际应用中,最常用的就是用call、apply去“借”另一个对象的方法来用,其实是call、apply改变了this指向。
20 | #### 上最简单的栗子
21 |
22 | 我写了个对象obj1,内部三个属性,两个数字numA、numB、还有个方法add,可以打印numA和numB之和:
23 |
24 | ```javascript
25 | var obj1 ={
26 | numA:1,
27 | numB:2,
28 | add:function(){
29 | console.log(this.numA + this.numB)
30 | }
31 | }
32 | obj1.add(); //打印出obj1.numA和obj1.numB的和,即3
33 | ```
34 |
35 | 现在我写了个对象obj2,内部有只两个属性数字numA和数字numB,没有计算器,但也想求和,怎么办?
36 | 管obj1借啊!怎么借?call、apply啊!
37 | 上代码
38 |
39 | ```javascript
40 | var obj2 = {
41 | numA:3,
42 | numB:4
43 | }
44 | //用call借:
45 | obj1.add.call(obj2); //打印出obj2.numA和obj2.numB的和,即7;
46 | //用apply借:
47 | obj1.add.apply(obj2); //打印出obj2.numA和obj2.numB的和,即7;
48 | ```
49 |
50 | 有意思吧?明明是obj1的add方法里出现了this,按照《理解JS中this指向的小技巧》中的思路,
51 | 找到的“.”左边是obj1,说明是obj1调用了add,add方法内部的this应该指向obj1啊!为啥算出来的结果都是obj2里的numA与numB之和呢?
52 | 因为用了call和apply啊!不是刚说完嘛,它们改变了this的指向啊,指向谁啊?第一个参数啊!第一个参数是谁啊?obj2啊!
53 | 所以你写obj1.add.call(obj2),add方法内部的this指向就变成了obj2,就打印出了obj2.numA和obj2.numB的和。
54 | 就起到了obj2向Obj1“借”了方法add的效果。
55 | #### 带参数的栗子
56 | 这个栗子是面向对象的栗子,对面向对象不够了解的同学,请尽量读懂[不得不提的原型/原型链](https://github.com/TerryBeanX2/Dive-Into-JS/tree/master/proto)
57 |
58 | 我写了个构造函数Obj1,内部三个属性,两个数字numA、numB、还有个方法add,可以打印numA和numB之和:
59 |
60 | ```javascript
61 | function Obj1(numA,numB){
62 | this.numA = numA;
63 | this.numB = numB;
64 | }
65 | Obj1.prototype.add = function(){
66 | console.log(this.numA + this.numB)
67 | }
68 | var obj1 = new Obj1(1,2);
69 | obj1.add(); //打印出obj1.numA和obj1.numB的和,即3
70 | ```
71 |
72 | 现在我写了个构造函数Obj2,内部有只两个属性数字numA和数字numB,没有计算器,但也想求和,怎么办?
73 | 管obj1借啊!怎么借?call、apply啊!
74 | 上代码
75 |
76 | ```javascript
77 | function Obj2(numA,numB){
78 | this.numA = numA;
79 | this.numB = numB;
80 | }
81 | var obj2 = new Obj2(3,4);
82 | //用call向实例obj1借:
83 | obj1.add.call(obj2,3,4); //打印出obj2.numA和obj2.numB的和,即7;
84 | //用apply向实例obj1借:
85 | obj1.add.apply(obj2,[3,4]); //打印出obj2.numA和obj2.numB的和,即7;
86 | //用call向构造函数Obj1借:
87 | Obj1.prototype.add.call(obj2, 3, 4); //打印出obj2.numA和obj2.numB的和,即7;
88 | //用apply向构造函数Obj1借:
89 | Obj1.prototype.add.apply(obj2, [3, 4]); //打印出obj2.numA和obj2.numB的和,即7;
90 | ```
91 |
92 | 这个栗子恰好说明了带参数的情况怎么“借”另一个对象的方法,也把apply和call的不同解释明白了,就是个传参不同。
93 | 看这个 Obj1.prototype.add.call(obj2, 3, 4) ,眼熟吗?
94 | 像不像 Array.prototype.forEach.call(xxx) ?就是这么来的,xxx想借用Array.prototype的forEach方法完成遍历。
95 | ## 3、特殊栗:在第一个参数为this并且this指向window的情况下,apply的应用
96 | 比如有个需求,需要做到每次调用先前别人写好的方法时,先在前面运行我们添加的代码:
97 | 下面的代码不一定是最好的实现本需求的代码,但可以演示apply的应用。
98 | 生动的具体化一下:
99 |
100 | ###### 先前陈海写的的代码:
101 |
102 | ```javascript
103 | function foo(){
104 | console.log('我是陈海,我拍床戏去了');
105 | }
106 | foo();
107 | ```
108 |
109 | 现在侯亮平接手的反贪局接管了代码,
110 | 需求是,不改变陈海写的代码的情况下,在每次调用陈海写的代码时先打印一些话。
111 |
112 | ###### 林华华自告奋勇,用一段代码帮侯局长完成了需求:
113 |
114 | ```javascript
115 | function beforeFoo(num){
116 | console.log('侯亮平知道陈海有床戏,一共'+num+'场');
117 | }
118 | var fooOld = foo;
119 | foo = function(num){
120 | beforeFoo(num); //这里将会被陆亦可修改
121 | fooOld();
122 | }
123 | foo(30); //运行一下看看效果
124 | ```
125 |
126 | ###### 陆亦可觉得这个代码复用性太低,每次beforeFoo的参数个数有变化,还要一同修改下面的代码,于是改进了一下:
127 |
128 | ```javascript
129 | function beforeFoo(num,text){
130 | console.log('侯亮平知道陈海有床戏,一共'+num+'场,',text);
131 | }
132 | var fooOld = foo;
133 | foo = function(){
134 | beforeFoo.apply(this,arguments); //陆亦可修改了这里
135 | fooOld();
136 | }
137 | foo(30,'醒不过来'); //运行一下看看效果
138 | ```
139 |
140 | 刹车!陆亦可在她的代码里用到了apply!
141 | 我们来分析一下她干了啥,完成了啥功能:
142 | 修改:把beforeFoo(num)改成beforeFoo.apply(this,arguments);
143 | 完成功能:beforeFoo可以任意修改参数个数,不必再修改后续代码。
144 |
145 | ##### 是不是挺神奇,我们来分析一下:?
146 |
147 | 首先来看看beforeFoo.apply(this,arguments)中的this:
148 | 1、this出现在新foo的内部;
149 | 2、foo的调用语句是foo(30,'醒不过来'),是全局直接调用,找不到“.”;
150 | 根据我上一篇this教程,通过这两点,不难发现this指向window;
151 |
152 | 那么,根据本片文章前面提到过的,apply即“借”,beforeFoo.apply(this,arguments),
153 | 也就是this借用了beforeFoo方法,向谁借的?beforeFoo左边没有“.”,是全局调用,原来是向window借的!
154 | 而刚刚说过,此this指向window,这就好玩了:window向window借用了beforeFoo方法!
155 |
156 | 你说,那不就是beforeFoo直接调用吗,绕一圈干嘛?别忘了还有arguments参数呢!
157 | 这么绕了一圈,在绕圈调用的过程中,JS会解析arguments参数,自动用“,”帮你把参数分开传入beforeFoo方法,
158 | 以后无论你如何修改beforeFoo方法的参数个数,都不用再改剩余的代码了。
159 | 陆亦可利用这一点,巧妙的借助apply完成了代码的可用性提高。
160 |
161 | PS:ES6新出的拓展符可以完成一样的效果:before.apply(this,arguments)可以写成before(...arguments);
162 | 请细细品味,发现道理都是想通的,有趣吧。
163 |
164 | 最后,侯亮平风骚的封装了代码,以后陈海再也不怕不知道自己会演多少场床戏了。
165 |
166 | ## 小结
167 | * 看到call、apply出现,遵循着“借”的思想,再配合“改变this指向”,
168 | * XX.call(YY),那么这个“XX”就是被借的方法;
169 | * YY就是借方法的那个对象,this指向它;
170 | * XX是谁的?谁调用就是谁的,XX左边没有“.”,说明是全局调用,那就是window的。
171 | * 一定要做到“不找出到底是向谁借的就不罢休”。
172 |
173 | #### 当你终于找到物主(到底是“借”的谁的方法),接着理清this指向,你也就透彻的明白call和apply了。
174 |
175 | 欢迎转载,需要注明原址。如果帮到你,希望得到你的Star~
176 | PS:教程之间紧密联系,不懂的地方,请好好看下[目录](https://github.com/TerryBeanX2/Dive-Into-JS#提供给有一定js基础开发者进阶知识点大白话解读),有没有你不懂的那个关键字在里面。
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------