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]
  • 相关阅读:
    Delphi公用函数单元
    Delphi XE5 for Android (十一)
    Delphi XE5 for Android (十)
    Delphi XE5 for Android (九)
    Delphi XE5 for Android (八)
    Delphi XE5 for Android (七)
    Delphi XE5 for Android (五)
    Delphi XE5 for Android (四)
    Delphi XE5 for Android (三)
    Delphi XE5 for Android (二)
  • 原文地址:https://www.cnblogs.com/shen076/p/6192722.html
Copyright © 2011-2022 走看看