zoukankan      html  css  js  c++  java
  • 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]
  • 相关阅读:
    CTFHub_技能树_文件上传
    QT入门-重载的信号槽
    QT入门-自定义信号
    C++: xx does not name a type报错
    HDU1166 敌兵布阵
    洛谷P2574 XOR的艺术(线段树)
    P3373 【模板】线段树 2(板子好题)
    SP1716 GSS3
    QT入门-自定义槽函数
    Educational Codeforces Round 87 (Rated for Div. 2) D. Multiset(树状数组/好题)
  • 原文地址:https://www.cnblogs.com/shen076/p/6192722.html
Copyright © 2011-2022 走看看