zoukankan      html  css  js  c++  java
  • underscore源码阅读

    1:函数式编程初探

    2:if(obj.length === +obj.length)的判断

    3:JS对象属性用中括号表示的优点在于可以用变量表示属性

    4:callee,caller---JS高级程序设计P114-115

    5:函数的length属性是希望接受的命名参数的个数,对象本身是没有length属性的

    6:call与apply---JS高级P116-117 ①传递参数②扩充作用域

    7:in运算符

    判断对象是否为数组/对象的元素/属性:
      格式:(变量 in 对象),
      当“对象”为数组时,“变量”指的是数组的“索引”;
      当“对象”为对象是,“变量”指的是对象的“属性”。
      var arr = ["a","b","2","3","str"];
      var result = ("b" in arr);
      var result1 = (4 in arr);  
      输出:
      false

    8:别名_.reduce = _.foldl = _.inject
    9:find内部其实使用的是some

    10:

    // 迭代集合中的元素, 并将通过处理器验证的元素放到数组中并返回
    each(obj, function(value, index, list) {
    if(iterator.call(context, value, index, list))
    results[results.length] = value;             //这个数组处理可以借鉴
    });

     11:

    // 依次调用集合中所有元素的同名方法, 从第3个参数开始, 将被以此传入到元素的调用方法中
    // 返回一个数组, 存储了所有方法的处理结果
    _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    var isFunc = _.isFunction(method);
    return _.map(obj, function(value) {
    var func = isFunc ? method : value[method];
    //确定func是什么
    return func == null ? func : func.apply(value, args);
    //如果func存在的话就进行函数运算,否则直接跳出
    });
    };

    12:

    // 返回集合中的最大值, 如果不存在可比较的值, 则返回undefined
    _.max = function(obj, iterator, context) {
    // 如果集合是一个数组, 且没有使用处理器, 则使用Math.max获取最大值
    // 一般会是在一个数组存储了一系列Number类型的数据
    if(!iterator && _.isArray(obj) && obj[0] === +obj[0])
    return Math.max.apply(Math, obj);
    // 对于空值, 直接返回负无穷大
    if(!iterator && _.isEmpty(obj))
    return -Infinity;
    // 一个临时的对象, computed用于在比较过程中存储最大值(临时的)
    var result = {
    computed : -Infinity
    };
    // 迭代集合中的元素
    each(obj, function(value, index, list) {
    // 如果指定了处理器参数, 则比较的数据为处理器返回的值, 否则直接使用each遍历时的默认值
    var computed = iterator ? iterator.call(context, value, index, list) : value;
    // 如果比较值相比上一个值要大, 则将当前值放入result.value
    computed >= result.computed && ( result = {
    value : value,
    computed : computed
    });
    });
    // 返回最大值

    return result.value;
    };

    13:clip-path视察滚动

    14:

    delay_.delay(function, wait, *arguments) 
    类似setTimeout,等待wait毫秒后调用function。如果传递可选的参数arguments,当函数function执行时,arguments 会作为参数传入。

    var log = _.bind(console.log, console);
    _.delay(log, 1000, 'logged later');
    => 'logged later' // Appears after one second.

    throttle_.throttle(function, wait, [options]) 
    创建并返回一个像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。(愚人码头注:详见:javascript函数的throttle和debounce,感谢 @澳利澳先生 的翻译建议)

    默认情况下,throttle将在你调用的第一时间尽快执行这个function,并且,如果你在wait周期内调用任意次数的函数,都将尽快的被覆盖。如果你想禁用第一次首先执行的话,传递{leading: false},还有如果你想禁用最后一次执行的话,传递{trailing: false}

    var throttled = _.throttle(updatePosition, 100);
    $(window).scroll(throttled);

    debounce_.debounce(function, wait, [immediate]) 
    返回 function 函数的防反跳版本, 将延迟函数的执行(真正的执行)在函数最后一次调用时刻的 wait 毫秒之后. 对于必须在一些输入(多是一些用户操作)停止到达之后执行的行为有帮助。 例如: 渲染一个Markdown格式的评论预览, 当窗口停止改变大小之后重新计算布局, 等等.

    传参 immediate 为 true, debounce会在 wait 时间间隔的开始调用这个函数 。(愚人码头注:并且在 waite 的时间之内,不会再次调用。)在类似不小心点了提交按钮两下而提交了两次的情况下很有用。 (感谢 @ProgramKid 的翻译建议)

    var lazyLayout = _.debounce(calculateLayout, 300);
    $(window).resize(lazyLayout);

    // debounce与throttle方法类似, 用于函数节流, 它们的不同之处在于:
    // -- throttle关注函数的执行频率, 在指定频率内函数只会被执行一次;
    // -- debounce函数更关注函数执行的间隔, 即函数两次的调用时间不能小于指定时间;
    // 如果两次函数的执行间隔小于wait, 定时器会被清除并重新创建, 这意味着连续频繁地调用函数, 函数一直不会被执行, 直到某一次调用与上一次调用的时间不小于wait毫秒
    // debounce函数一般用于控制需要一段时间之后才能执行的操作, 例如在用户输入完毕200ms后提示用户, 可以使用debounce包装一个函数, 绑定到onkeyup事件

    15:

    extend_.extend(destination, *sources) 
    复制source对象中的所有属性覆盖到destination对象上,并且返回 destination 对象. 复制是按顺序的, 所以后面的对象属性会把前面的对象属性覆盖掉(如果有重复).

    _.extend({name: 'moe'}, {age: 50});
    => {name: 'moe', age: 50}

    16:

    mixin_.mixin(object) 
    允许用您自己的实用程序函数扩展Underscore。传递一个 {name: function}定义的哈希添加到Underscore对象,以及面向对象封装。

    _.mixin({
      capitalize: function(string) {
        return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
      }
    });
    _("fabio").capitalize(); _.capitalize("fabio");这两种写法都可以
    => "Fabio"

    17.链式语法(Chaining)

    您可以在面向对象或者函数的风格下使用Underscore, 这取决于您的个人偏好. 以下两行代码都可以 把一个数组里的所有数字乘以2.

    _.map([1, 2, 3], function(n){ return n * 2; });
    _([1, 2, 3]).map(function(n){ return n * 2; });

    chain_.chain(obj) 
    返回一个封装的对象. 在封装的对象上调用方法会返回封装的对象本身, 直道 value 方法调用为止.

    var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
    var youngest = _.chain(stooges)
      .sortBy(function(stooge){ return stooge.age; })
      .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
      .first()
      .value();
    => "moe is 21"

    18:template_.template(templateString, [settings]) 
    API:

    将 JavaScript 模板编译为可以用于页面呈现的函数, 对于通过JSON数据源生成复杂的HTML并呈现出来的操作非常有用。 模板函数可以使用 <%= … %>插入变量, 也可以用<% … %>执行任意的 JavaScript 代码。 如果您希望插入一个值, 并让其进行HTML转义,请使用<%- … %>。 当你要给模板函数赋值的时候,可以传递一个含有与模板对应属性的data对象 。 如果您要写一个一次性的, 您可以传对象 data 作为第二个参数给模板 template 来直接呈现, 这样页面会立即呈现而不是返回一个模板函数. 参数 settings 是一个哈希表包含任何可以覆盖的设置 _.templateSettings.

    1 写法一
    2 var template = _.template("<b><%- value %></b>");
    3 template({value: '<script>'});
    4 => "<b>&lt;script&gt;</b>"
    5 写法二
    6 var template = _.template("<b><%- value %></b>")({value: '<script>'});
    7 都可以

    源码分析:(之所以)_.template(!@#)(data);

    // 创建一个函数, 将源码作为函数执行体, 将obj和Underscore作为参数传递给该函数
    var render = new Function(settings.variable || 'obj', '_', source);
    // 如果指定了模板的填充数据, 则替换模板内容, 并返回替换后的结果
    if(data)
    return render(data, _);
    // 如果没有指定填充数据, 则返回一个函数, 该函数用于将接收到的数据替换到模板
    // 如果在程序中会多次填充相同模板, 那么在第一次调用时建议不指定填充数据, 在获得处理函数的引用后, 再直接调用会提高运行效率
    var template = function(data) {
    return render.call(this, data, _);
    };

    19:①将内置对象常用方法缓存在局部变量中方便调用 ②对call的使用 ③各种判断 ④别名

  • 相关阅读:
    CSS
    WebStorm快捷键
    每日一题
    周末了周末了
    集合,个人理解
    Linux学习笔记
    Java对象的序列化和反序列化实践
    Android 实现蘑菇街购物车动画效果
    【转】android手势处理揭秘
    【转】android 手势识别和VelocityTracker
  • 原文地址:https://www.cnblogs.com/cndotabestdota/p/5665743.html
Copyright © 2011-2022 走看看