JavaScript全面学习(中高)

1.当代码块被try { ... }包裹的时候,就表示这部分代码执行过程中可能会发生错误,一旦发生错误,就不再继续执行后续代码,转而跳到catch块。catch (e) { ... }包裹的代码就是错误处理代码,变量e表示捕获到的错误。

    最后,无论有没有错误,finally一定会被执行。

    catchfinally可以不必都出现

  throw语句主动抛出一个错误,让执行流程直接跳转到catch块。

    当我们用catch捕获错误时,一定要编写错误处理语句,哪怕仅仅把错误打印console.log出来,也不要什么也不干。

    如果在一个函数内部发生了错误,它自身没有捕获,错误就会被抛到外层调用函数,如果外层函数也没有捕获,该错误会一直沿着函数调用链向上抛出,直到被JavaScript引擎捕获,代码终止执行。

2.

function printTime() {
    throw new Error();
}

try {
    setTimeout(printTime, 1000);
    console.log('done');
} catch (e) {
    alert('error');
}

这段代码无法弹出error,原因就在于调用setTimeout()函数时,传入的printTime函数并未立刻执行!紧接着,JavaScript引擎会继续执行console.log('done');语句,而此时并没有错误发生。直到1秒钟后,执行printTime函数时才发生错误,但此时除了在printTime函数内部捕获错误外,外层代码并无法捕获。(全部函数执行完毕,再处理1000ms后的函数)

所以,涉及到异步代码,无法在调用时捕获,原因就是在捕获的当时,回调函数并未执行。

类似的,当我们处理一个事件时,在绑定事件的代码处,无法捕获事件处理函数的错误。

3.underscore.js

实现map()操作(可以作用于Object):

_.map([1, 2, 3], (x) => x * x); // [1, 4, 9]
_.map({ a: 1, b: 2, c: 3 }, (v, k) => k + '=' + v); // ['a=1', 'b=2', 'c=3']

4.every / some

'use strict';
// 所有元素都大于0?
_.every([1, 4, 7, -3, -9], (x) => x > 0); // false
// 至少一个元素大于0?
_.some([1, 4, 7, -3, -9], (x) => x > 0); // true

5.max / min

'use strict';
var arr = [3, 5, 7, 9];
_.max(arr); // 9
_.min(arr); // 3

// 空集合会返回-Infinity和Infinity,所以要先判断集合不为空:
_.max([])
-Infinity
_.min([])
Infinity

如果集合是Object,max()min()只作用于value,忽略掉key:

_.max({ a: 1, b: 2, c: 3 }); // 3

6.groupBy()把集合的元素按照key归类,key由传入的函数返回:

'use strict';

var scores = [20, 81, 75, 40, 91, 59, 77, 66, 72, 88, 99];
var groups = _.groupBy(scores, function (x) {
    if (x < 60) {
        return 'C';
    } else if (x < 80) {
        return 'B';
    } else {
        return 'A';
    }
});
// 结果:
// {
//   A: [81, 91, 88, 99],
//   B: [75, 77, 66, 72],
//   C: [20, 40, 59]
// }

7.shuffle / sample

  shuffle()用洗牌算法随机打乱一个集合:

'use strict';
// 注意每次结果都不一样:
_.shuffle([1, 2, 3, 4, 5, 6]); // [3, 5, 4, 6, 2, 1]

sample()随机选择一个或多个元素:

'use strict';
// 注意每次结果都不一样:
// 随机选1个:
_.sample([1, 2, 3, 4, 5, 6]); // 2
// 随机选3个:
_.sample([1, 2, 3, 4, 5, 6], 3); // [6, 1, 4]

8.flatten()接收一个Array,无论这个Array里面嵌套了多少个Arrayflatten()最后都把它们变成一个一维数组:

_.flatten([1, [2], [3, [[4], [5]]]]); // [1, 2, 3, 4, 5]

9.first / last

var arr = [2, 4, 6, 8];
_.first(arr); // 2
_.last(arr); // 8

10.zip / unzip

var names = ['Adam', 'Lisa', 'Bart'];
var scores = [85, 92, 59];
_.zip(names, scores);
// [['Adam', 85], ['Lisa', 92], ['Bart', 59]]
var namesAndScores = [['Adam', 85], ['Lisa', 92], ['Bart', 59]];
_.unzip(namesAndScores);
// [['Adam', 'Lisa', 'Bart'], [85, 92, 59]]

11.object

var names = ['Adam', 'Lisa', 'Bart'];
var scores = [85, 92, 59];
_.object(names, scores);
// {Adam: 85, Lisa: 92, Bart: 59}

12.range

// 从0开始小于10:
_.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// 从1开始小于11:
_.range(1, 11); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 从0开始小于30,步长5:
_.range(0, 30, 5); // [0, 5, 10, 15, 20, 25]

// 从0开始大于-10,步长-1:
_.range(0, -10, -1); // [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

13.bind.   如果你想用log()取代console.log(),可以这样写:

var log = console.log;
// 调用call并传入console对象作为this:
log.call(console, 'Hello, world!')
// 输出Hello, world!

如果用bind,把console对象直接绑定在log()this指针上。可以这样写:

var log = _.bind(console.log, console);
log('Hello, world!');
// 输出Hello, world!

14.partial()为一个函数创建偏函数

    假设我们经常计算2y,每次都写Math.pow(2, y)就比较麻烦,如果创建一个新的函数能直接这样写pow2N(y)就好了,这个新函数pow2N(y)就是根据Math.pow(x, y)创建出来的偏函数,它固定住了原函数的第一个参数(始终为2):

var pow2N = _.partial(Math.pow, 2);
pow2N(3); // 8
pow2N(5); // 32
pow2N(10); // 1024

  如果我们不想固定第一个参数,想固定第二个参数,比如,希望创建一个偏函数cube(x),计算x3,可以用_作占位符,固定住第二个参数:

var cube = _.partial(Math.pow, _, 3);
cube(3); // 27
cube(5); // 125
cube(10); // 1000

15.memoize能把结果缓存下来,再次调用不需要计算:

var factorial = _.memoize(function(n) {
    console.log('start calculate ' + n + '!...');
    var s = 1, i = n;
    while (i > 1) {
        s = s * i;
        i --;
    }
    console.log(n + '! = ' + s);
    return s;
});

// 第一次调用:
factorial(10); // 3628800
// 注意控制台输出:
// start calculate 10!...
// 10! = 3628800

// 第二次调用:
factorial(10); // 3628800
// 控制台没有输出            但是,当你计算factorial(9)的时候,仍然会重新计算

令每一次都保存:

var factorial = _.memoize(function(n) {
    console.log('start calculate ' + n + '!...');
    if (n < 2) {
        return 1;
    }
    return n * factorial(n - 1);
});

factorial(10); // 3628800
// 输出结果说明factorial(1)~factorial(10)都已经缓存了:
// start calculate 10!...
// start calculate 9!...
// start calculate 8!...
// start calculate 7!...
// start calculate 6!...
// start calculate 5!...
// start calculate 4!...
// start calculate 3!...
// start calculate 2!...
// start calculate 1!...

factorial(9); // 362880
// console无输出

 16.once()保证某个函数执行且仅执行一次

17.delay()可以让一个函数延迟执行

var log = _.bind(console.log, console);
_.delay(log, 2000, 'Hello,', 'world!');
// 2秒后打印'Hello, world!':

18.keys / allKeys

keys()可以非常方便地返回一个object自身所有的key,但不包含从原型链继承下来的:

function Student(name, age) {
    this.name = name;
    this.age = age;
}

var xiaoming = new Student('小明', 20);
_.keys(xiaoming); // ['name', 'age']

allKeys()除了object自身的key,还包含从原型链继承下来的

19.values

    和keys()类似,values()返回object自身但不包含原型链继承的所有值

20.mapObject()就是针对object的map版本:

var obj = { a: 1, b: 2, c: 3 };
// 注意传入的函数签名,value在前,key在后:
_.mapObject(obj, (v, k) => 100 + v); // { a: 101, b: 102, c: 103 }

21.invert()把object的每个key-value来个交换,key变成value,value变成key:

var obj = {
    Adam: 90,
    Lisa: 85,
    Bart: 59
};
_.invert(obj); // { '59': 'Bart', '85': 'Lisa', '90': 'Adam' }

22.extend()把多个object的key-value合并到第一个object并返回:

var a = {name: 'Bob', age: 20};
_.extend(a, {age: 15}, {age: 88, city: 'Beijing'}); // {name: 'Bob', age: 88, city: 'Beijing'}
// 变量a的内容也改变了:
a; // {name: 'Bob', age: 88, city: 'Beijing'}

       注意:如果有相同的key,后面的object的value将覆盖前面的object的value。

   extendOwn()extend()类似,但获取属性时忽略从原型链继承下来的属性。

23.clone()方法会把原有对象的所有属性都复制到新的对象中。

      注意,clone()是“浅复制”。所谓“浅复制”就是说,两个对象相同的key所引用的value其实是同一对象:

source.skills === copied.skills; // true

      修改source.skills会影响copied.skills

24.isEqual()对两个object进行深度比较,如果内容完全相同,则返回true

var o1 = { name: 'Bob', skills: { Java: 90, JavaScript: 99 }};
var o2 = { name: 'Bob', skills: { JavaScript: 99, Java: 90 }};

o1 === o2; // false
_.isEqual(o1, o2); // true
var o1 = ['Bob', { skills: ['Java', 'JavaScript'] }];
var o2 = ['Bob', { skills: ['Java', 'JavaScript'] }];

o1 === o2; // false
_.isEqual(o1, o2); // true

24.

_.filter(_.map([1, 4, 9, 16, 25], Math.sqrt), x => x % 2 === 1);
// [1, 3, 5]

等效于下面的链式:

_.chain([1, 4, 9, 16, 25])
 .map(Math.sqrt)
 .filter(x => x % 2 === 1)
 .value();
// [1, 3, 5]
原文地址:https://www.cnblogs.com/shen076/p/6192722.html