update: 剩余参数
This commit is contained in:
parent
0c410c9736
commit
72be5e546f
@ -58,7 +58,7 @@ obj2:{"name":"qianguyihao","age":28,"info":{"desc":"永不止步"}}
|
|||||||
obj2 = Object.assgin(obj2, obj1);
|
obj2 = Object.assgin(obj2, obj1);
|
||||||
```
|
```
|
||||||
|
|
||||||
**解释**:将`obj1` 拷贝给 `obj2`。
|
**解释**:将`obj1` 拷贝给 `obj2`。执行完毕后,obj2 的值会被更新。
|
||||||
|
|
||||||
**作用**:将 obj1 的值追加到 obj2 中。如果对象里的属性名相同,会被覆盖。
|
**作用**:将 obj1 的值追加到 obj2 中。如果对象里的属性名相同,会被覆盖。
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ const obj2 = {
|
|||||||
sex: '男',
|
sex: '男',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 浅拷贝:把 obj1 赋值给 obj2。这一行,是关键代码
|
// 浅拷贝:把 obj1 赋值给 obj2。这一行,是关键代码。这行代码的返回值也是 obj2
|
||||||
Object.assign(obj2, obj1);
|
Object.assign(obj2, obj1);
|
||||||
|
|
||||||
console.log(JSON.stringify(obj2));
|
console.log(JSON.stringify(obj2));
|
||||||
|
@ -89,7 +89,7 @@ console.log(fn2(1)); //输出结果:2
|
|||||||
|
|
||||||
ES6 之前的普通函数中:this 指向的是函数被调用的对象(也就是说,谁调用了函数,this 就指向谁)。
|
ES6 之前的普通函数中:this 指向的是函数被调用的对象(也就是说,谁调用了函数,this 就指向谁)。
|
||||||
|
|
||||||
而 ES6 的箭头函数中:箭头函数不绑定 this,this 指向的是**箭头函数定义位置的 this**(也就是说,箭头函数在哪个位置定义的,this 就指向哪里)。
|
而 ES6 的箭头函数中:**箭头函数本身不绑定 this**,this 指向的是**箭头函数定义位置的 this**(也就是说,箭头函数在哪个位置定义的,this 就跟这个位置的this指向相同)。
|
||||||
|
|
||||||
代码举例:
|
代码举例:
|
||||||
|
|
||||||
@ -118,6 +118,27 @@ obj
|
|||||||
|
|
||||||
上面的代码中,箭头函数是在 fn1()函数里面定义的,所以第二个 this 跟 第一个 this 指向的是**同一个位置**。又因为,在执行 `fn1.call(obj)`之后,第一个 this 就指向了 obj,所以第二个 this 也是指向 了 obj。
|
上面的代码中,箭头函数是在 fn1()函数里面定义的,所以第二个 this 跟 第一个 this 指向的是**同一个位置**。又因为,在执行 `fn1.call(obj)`之后,第一个 this 就指向了 obj,所以第二个 this 也是指向 了 obj。
|
||||||
|
|
||||||
|
|
||||||
|
### 面试题:箭头函数的this指向
|
||||||
|
|
||||||
|
代码举例:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const name = '许嵩';
|
||||||
|
const obj = {
|
||||||
|
name: '千古壹号',
|
||||||
|
sayHello: () => {
|
||||||
|
console.log(this.name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.sayHello();
|
||||||
|
```
|
||||||
|
|
||||||
|
上方代码的打印结果是什么?你可能很难想到。
|
||||||
|
|
||||||
|
正确答案的打印结果是`许嵩`。因为 `obj` 这个对象并不产生作用域, `sayHello()` 这个箭头函数实际仍然是定义在 window 当中的,所以 这里的 this指向是 window。
|
||||||
|
|
||||||
## 参数默认值
|
## 参数默认值
|
||||||
|
|
||||||
**传统写法**:
|
**传统写法**:
|
||||||
@ -185,7 +206,7 @@ fn('vae');
|
|||||||
|
|
||||||
此时打印结果是:`vae smyh`。
|
此时打印结果是:`vae smyh`。
|
||||||
|
|
||||||
## 扩展运算符
|
## 扩展运算符(剩余参数)
|
||||||
|
|
||||||
注意区分:
|
注意区分:
|
||||||
|
|
||||||
@ -193,9 +214,11 @@ fn('vae');
|
|||||||
|
|
||||||
- rest 运算符的格式为`...变量名`
|
- rest 运算符的格式为`...变量名`
|
||||||
|
|
||||||
有了 ES6,当我们在定义一个方法,但是不确定其参数的个数时,我们就可以用**扩展运算符**作为参数。
|
**剩余参数**允许我们将一个不确定数量的参数表示为一个**数组**。
|
||||||
|
|
||||||
以前,我们在定义方法时,参数要确定个数,如下:(程序会报错)
|
**传统写法**:
|
||||||
|
|
||||||
|
ES5 中,在定义方法时,参数要确定个数,如下:(程序会报错)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function fn(a, b, c) {
|
function fn(a, b, c) {
|
||||||
@ -212,7 +235,9 @@ fn(1, 2, 3);
|
|||||||
|
|
||||||
![](http://img.smyhvae.com/20180304_1638.png)
|
![](http://img.smyhvae.com/20180304_1638.png)
|
||||||
|
|
||||||
现在,我们有了扩展运算符,就不用担心报错的问题了。代码可以这样写:
|
**ES6写法**:
|
||||||
|
|
||||||
|
ES6中,我们有了扩展运算符,就不用担心报错的问题了。代码可以这样写:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function fn(...arg) {
|
function fn(...arg) {
|
||||||
@ -223,14 +248,44 @@ function fn(...arg) {
|
|||||||
console.log(arg[3]);
|
console.log(arg[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn(1, 2, 3); //方法中定义了四个参数,但只引用了三个参数,ES6 中并不会报错。
|
fn(1, 2, 3); //方法的定义中了四个参数,但调用函数时只使用了三个参数,ES6 中并不会报错。
|
||||||
```
|
```
|
||||||
|
|
||||||
![](http://img.smyhvae.com/20180304_1650.png)
|
![](http://img.smyhvae.com/20180304_1650.png)
|
||||||
|
|
||||||
上方代码中注意,arg 参数之后,不能再加别的参数,否则编译报错。
|
上方代码中注意,arg 参数之后,不能再加别的参数,否则编译报错。
|
||||||
|
|
||||||
**举例:**数组赋值的问题
|
还可以这样写:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function fn1(first, ...args) {
|
||||||
|
console.log(first); // 10
|
||||||
|
console.log(args); // 数组:[20, 30]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn1(10, 20, 30);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 剩余参数的举例
|
||||||
|
|
||||||
|
**举例1**:将参数求和
|
||||||
|
|
||||||
|
代码举例:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function fn1(...args) {
|
||||||
|
let sum = 0;
|
||||||
|
args.forEach(item => sum += item);
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
console.log(fn1(10, 20, 30));
|
||||||
|
```
|
||||||
|
|
||||||
|
打印结果;60
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**举例2**:数组赋值的问题
|
||||||
|
|
||||||
我们来分析一段代码:(将数组 arr1 赋值给 arr2)
|
我们来分析一段代码:(将数组 arr1 赋值给 arr2)
|
||||||
|
|
||||||
|
60
06-JavaScript进阶/02-数据的赋值.md
Normal file
60
06-JavaScript进阶/02-数据的赋值.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
|
||||||
|
## 对象赋值
|
||||||
|
|
||||||
|
|
||||||
|
### 用 Object.assgin() 实现浅拷贝
|
||||||
|
|
||||||
|
代码举例:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const obj1 = {
|
||||||
|
name: 'qianguyihao',
|
||||||
|
age: 28,
|
||||||
|
desc: 'hello world',
|
||||||
|
};
|
||||||
|
|
||||||
|
const obj2 = {
|
||||||
|
name: '许嵩',
|
||||||
|
sex: '男',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 【关键代码】浅拷贝:把 obj1 赋值给 obj2。这行代码的返回值也是 obj2
|
||||||
|
Object.assign(obj2, obj1);
|
||||||
|
|
||||||
|
console.log(JSON.stringify(obj2));
|
||||||
|
```
|
||||||
|
|
||||||
|
打印结果:
|
||||||
|
|
||||||
|
```
|
||||||
|
{"name":"qianguyihao","sex":"男","age":28,"desc":"hello world"}
|
||||||
|
```
|
||||||
|
|
||||||
|
注意,**上面这行代码在实际开发中,会经常遇到,一定要掌握**。它的作用是:将 obj1 的值追加到 obj2 中。如果两个对象里的属性名相同,则 obj12 中的值会被 obj2 中的值覆盖。
|
||||||
|
|
||||||
|
|
||||||
|
## 数组赋值
|
||||||
|
|
||||||
|
### 扩展运算符
|
||||||
|
|
||||||
|
```js
|
||||||
|
arr2 = arr1;
|
||||||
|
```
|
||||||
|
|
||||||
|
上方代码中,其实是让 arr2 指向 arr1 的地址。也就是说,二者指向的是同一个内存地址。
|
||||||
|
|
||||||
|
如果不想让 arr1 和 arr2 指向同一个内存地址,我们可以借助扩展运算符来做:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
let arr2 = [...arr1]; //arr2 会开辟新的内存地址
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
参考链接:
|
||||||
|
|
||||||
|
- [javaScript中浅拷贝和深拷贝的实现](https://github.com/wengjq/Blog/issues/3)
|
||||||
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
## 浅拷贝
|
|
||||||
|
|
||||||
对于对象或数组类型,当我们将a赋值给b,然后更改b中的属性,a也会随着变化。
|
|
||||||
|
|
||||||
也就是说,a和b指向了同一块堆内存,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝。
|
|
||||||
|
|
||||||
## 深拷贝
|
|
||||||
|
|
||||||
那么相应的,如果给b放到新的内存中,将a的各个属性都复制到新内存里,就是深拷贝。
|
|
||||||
|
|
||||||
也就是说,当b中的属性有变化的时候,a内的属性不会发生变化。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
参考链接:
|
|
||||||
|
|
||||||
- [深拷贝与浅拷贝的实现(一)](http://www.alloyteam.com/2017/08/12978/)
|
|
||||||
|
|
||||||
- [javaScript中浅拷贝和深拷贝的实现](https://github.com/wengjq/Blog/issues/3)
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user