0%

JS初学笔记

扩展运算符

扩展运算符就是... 不懂的情况下阅读难度笔记大,学会了以后非常好用
扩展运算符主要有两个作用

  1. 将一个数组转为用逗号分隔的参数序列
  2. 表示剩下的所有参数,并且合并成一个数组.

第一种情况主要是用来合并数组的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];

// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

第二种情况主要是用来赋值的

1
2
3
4
5
6
7
8
9
10
11
12
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest // []:

const [first, ...rest] = ["foo"];
first // "foo"
rest // []
// 要注意的是...rest这样的写法只能放在最后,如果作为第一个参数,就没有意义了

=>箭头函数

简单的说就是把function(参数1,参数2){}化简了 (参数1,参数2) =>{}

这样不仅看起来直接的多,而且写起来也方便,因为JS中很多回调函数都是匿名的,并不需要那么完整的格式.
但是,这当然不仅仅只是一个语法糖,在=>函数里,this的作用域会变,这里的this指向的是定义他的那个对象,而不是当前的对象.所以在使用的时候要注意,并且别什么情况下都使用=>函数

1
2
3
4
5
6
7
8
// 正常函数写法
[1,2,3].map(function (x) {
return x * x;
});

// 箭头函数写法
[1,2,3].map(x => x * x)
//当只有一个参数时不需要括号也可以

最后的升级版就是把扩展运算符和箭头函数合并在一起使用

1
2
3
4
5
6
7
8
9
const numbers = (...nums) => nums;

numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

const headAndTail = (head, ...tail) => [head, tail];

headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

还要注意一点=>函数不能使用yield命令,所以不能用作Generator函数,也不可以当做构造函数,即不可使用new命令.总结,=>函数就是用在回调函数等比较简单的匿名函数里,方便写,方便看.

变量的解构赋值

es6变量的赋值比较方便,比如
let [a,b,c] = [1,2,3];
对于数组的赋值,就是要位置对,结构对就可以赋值了.比如
let [foo, [[bar],baz] = [1,[[2],3]];
如果位置或者结构对不上,那数组的赋值是不行的,报undefined

另一种情况,是对象的解构赋值,对象的更方便,只要名字对的上就好了
let{foo, bar} = {foo:’123’,bar:’321’}
其实顺序位置对不上也是可以的,只要名字一样就好了,这就带来的异常的方便.

使用:

[x,y] = [y,x]直接就交换x和y的值了
比如后端返回给前端一个对象obj,前端不用一个个的赋值let a = obj.a,b = obj.b这样麻烦死,用解构赋值以后只要 let{a,b} = obj;前端或者说只要对方只要你的变量叫什么名字,就可以从你封装好的对象里,得到这个值,非常快速方便的赋值.之前看到的const React,{PropTypes} from ‘react’也是一样的道理,这里的{PropTypes}就是react的一个属性可以写成是react.PropTyes

map

map有两种用法

  1. 数组对象的一个遍历方法
  2. 一种数据结构

    当做遍历时,简单的说就是把数组当前的每一个值,依次的传到参数()中例如

1
2
3
4
5
let nub = [2,3,4,5];
function sqrt(n){
return n*n;
}
let sqrt = nub.map(sqrt) // 4,9,16,25

所以这第一种情况大多是函数遍历一个数组,只不过写法主动被动上有点不同

这第二种情况呢,map是一个Object的变形

他比object多的就是他的key不仅仅可以是string,可以是各种类型的值,甚至还包括对象,所以在hash结构上,map是一种比object很好的数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//true作为键
var m = new Map([
[true, ‘foo’],
[‘true’, ‘bar’]
]);

m.get(true) // ‘foo’
m.get(‘true’) // ‘bar’

var map = new Map([
[‘name’, ‘张三’],
[‘title’, ‘Author’]
]);

map.size // 2
map.has(‘name’) // true
map.get(‘name’) // “张三”
map.has(‘title’) // true
map.get(‘title’) // “Author”

var items = [
[‘name’, ‘张三’],
[‘title’, ‘Author’]
];
var map = new Map();
items.forEach(([key, value]) => map.set(key, value));

Map这个对象还内置了5个方法和一个属性,

  • get(key)
  • set(key)
  • has(key)
  • delete(key)
  • clear()
  • size(属性)
    还带了4个遍历器
  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历Map的所有成员。

这里顺便讲一下数组的遍历方法 forEach,map, reduce, filter

假设我们有一个数组,每个元素是一个人。你面前站了一排人。

foreach 就是你按顺序一个一个跟他们做点什么,具体做什么:

1
2
3
people.forEach(function (dude) {
dude.pickUpSoap();
})

forEach还有另一种用法forEach(args,callback),这里的args是回调函数执行forEach的作用域.

map 就是你手里拿一个盒子(一个新的数组),一个一个叫他们把钱包扔进去。结束的时候你获得了一个新的数组,里面是大家的钱包,钱包的顺序和人的顺序一一对应。

1
2
3
var wallets = people.map(function (dude) {  
return dude.wallet;
});

reduce 就是你拿着钱包,一个一个数过去看里面有多少钱啊?每检查一个,你就和前面的总和加一起来。这样结束的时候你就知道大家总共有多少钱了。

1
2
3
var totalMoney = wallets.reduce(function (countedMoney, wallet) {
return countedMoney + wallet.money;
}, 0);

补充一个 filter 的:你一个个钱包数过去的时候,里面钱少于 100 块的不要(留在原来的盒子里),多于 100 块的丢到一个新的盒子里。这样结束的时候你又有了一个新的数组,里面是所有钱多于 100 块的钱包:

1
2
3
var fatWallets = wallets.filter(function (wallet) {
return wallet.money > 100;
});

apply,call,bind

apply、call
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function fruits() {}

fruits.prototype = {
color: "red",
say: function() {
console.log("My color is " + this.color);
}
}

var apple = new fruits;
apple.say(); //My color is red
banana = {
color: "yellow"
}
apple.say.call(banana); //My color is yellow
apple.say.apply(banana); //My color is yellow

所以,可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 object 没有某个方法(本栗子中banana没有say方法),但是其他的有(本栗子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。

apply、call 的区别

对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。例如,有一个函数定义如下:

1
2
var func = function(arg1, arg2) {
};

就可以通过如下方式来调用:

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

其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
而bind,其实作用和apply还有call差不多
区别在于后者是立即执行,而bind是稍后执行
而且JavaScript中多次绑定是无效的,只有第一个绑定的对象有效