Skip to content

Commit

Permalink
add: call()、apply()、bind()的区别
Browse files Browse the repository at this point in the history
  • Loading branch information
qianguyihao committed Jul 4, 2020
1 parent 7d44e5a commit 1c075a0
Show file tree
Hide file tree
Showing 13 changed files with 449 additions and 229 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"printWidth": 300,
"tabWidth": 2,
"tabWidth": 4,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
Expand Down
85 changes: 85 additions & 0 deletions 04-JavaScript基础/18-函数.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,91 @@ function fn(){

我们可以这样说,如果直接是`fn()`,那就说明是函数调用。如果是`XX.fn()`的这种形式,那就说明是**方法**调用。


## 类数组 arguments

> 这部分,小白可能看不懂。所以,这一段,暂时可以忽略。

在调用函数时,浏览器每次都会传递进两个隐含的参数:

- 1.函数的上下文对象 this

- 2.**封装实参的对象** arguments

例如:

```javascript
function foo() {
console.log(arguments);
console.log(typeof arguments);
}
foo();
```

![](http://img.smyhvae.com/20180315_0903.png)

arguments 是一个类数组对象,它可以通过索引来操作数据,也可以获取长度。

**arguments 代表的是实参**。在调用函数时,我们所传递的实参都会在 arguments 中保存。有个讲究的地方是:arguments**只在函数中使用**

### 1、返回函数**实参**的个数:arguments.length

arguments.length 可以用来获取**实参的长度**

举例:

```javascript
fn(2, 4);
fn(2, 4, 6);
fn(2, 4, 6, 8);
function fn(a, b) {
console.log(arguments);
console.log(fn.length); //获取形参的个数
console.log(arguments.length); //获取实参的个数
console.log('----------------');
}
```

打印结果:

![](http://img.smyhvae.com/20180125_2140.png)

我们即使不定义形参,也可以通过 arguments 来使用实参(只不过比较麻烦):arguments[0] 表示第一个实参、arguments[1] 表示第二个实参...

### 2、返回正在执行的函数:arguments.callee

arguments 里边有一个属性叫做 callee,这个属性对应一个函数对象,就是当前正在指向的函数对象。

```javascript
function fun() {
console.log(arguments.callee == fun); //打印结果为true
}
fun('hello');
```

在使用函数**递归**调用时,推荐使用 arguments.callee 代替函数名本身。

### 3、arguments 可以修改元素

之所以说 arguments 是伪数组,是因为:**arguments 可以修改元素,但不能改变数组的长短**。举例:

```javascript
fn(2, 4);
fn(2, 4, 6);
fn(2, 4, 6, 8);
function fn(a, b) {
arguments[0] = 99; //将实参的第一个数改为99
arguments.push(8); //此方法不通过,因为无法增加元素
}
```



## arguments 的使用

当我们不确定有多少个参数传递的时候,可以用 **arguments** 来获取。在 JavaScript 中,arguments 实际上是当前函数的一个**内置对象**。所有函数都内置了一个 arguments 对象(只有函数才有 arguments 对象),arguments 对象中存储了**传递的所有实参**.
Expand Down
109 changes: 109 additions & 0 deletions 04-JavaScript基础/21-this指向.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
## 执行期上下文

**函数执行**时(准确来说,是在函数发生预编译的前一刻),会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境。

每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立且独一无二的。当函数执行完毕,它所产生的执行期上下文会被销毁。

参考链接:<https://www.cnblogs.com/chenyingjie1207/p/9966036.html>

## this

解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是 this,this 指向的是一个对象,这个对象我们称为函数执行的 上下文对象。

### 函数内 this 的指向【非常重要】

我们在《JavaScript 基础/函数.md》这篇文章讲过,函数的调用有**六种**形式。

根据函数的调用方式的不同,this 会指向不同的对象:

- 1.以函数的形式(包括普通函数、定时器函数、立即执行函数)调用时,this 的指向永远都是 window。比如`fun();`相当于`window.fun();`

- 2.以方法的形式调用时,this 指向调用方法的那个对象

- 3.以构造函数的形式调用时,this 指向实例对象

- 4.以事件绑定函数的形式调用时,this 指向**绑定事件的对象**

- 5.使用 call apply 调用时,this 指向指定的那个对象

**针对第 1 条的举例**

```javascript
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: 'smyh',
sayName: fun,
};
var obj2 = {
name: 'vae',
sayName: fun,
};
var name = '全局的name属性';
//以函数形式调用,this是window
fun(); //可以理解成 window.fun()
```

打印结果:

```
Window
全局的name属性
```

上面的举例可以看出,this 指向的是 window 对象,所以 this.name 指的是全局的 name。

** 2 条的举例**

```javascript
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: 'smyh',
sayName: fun,
};
var obj2 = {
name: 'vae',
sayName: fun,
};
var name = '全局的name属性';
//以方法的形式调用,this是调用方法的对象
obj2.sayName();
```

打印结果:

```
Object
vae
```

上面的举例可以看出,this 指向的是 对象 obj2 ,所以 this.name 指的是 obj2.name。

### 箭头函数中 this 的指向

ES6 中的箭头函数并不会使用上面的准则,而是会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。

### 改变函数内部的 this 指向

JS 专门为我们提供了一些方法来改变函数内部的 this 指向。详见下一篇文章中的 call()、apply()、bind() 方法。

## 我的公众号

想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。

扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:

![](http://img.smyhvae.com/20200101.png)
15 changes: 0 additions & 15 deletions 04-JavaScript基础/21-执行期上下文.md

This file was deleted.

Loading

0 comments on commit 1c075a0

Please sign in to comment.