zoukankan      html  css  js  c++  java
  • extend 方法在js框架中的设计

    今天来分析下extend方法在各种js框架下的设计。这个函数的功能基本都是实现对象的拷贝功能,即将一个对象的所有属属性拷贝到另外一个对象上去,这个函数使用的频率也很高,如果我们要将一个类的所有方法拷贝到另外方法上去,使用这个方法很方便的。

    1)在百度tangram js 框架中的实现,

    baidu.extend =
    baidu.object.extend = function (target, source) {
        for (var p in source) {
            if (source.hasOwnProperty(p)) {
                target[p] = source[p];
            }
        }
        
        return target;
    };
    仅有2个参数,extend(target,source),第一个参数是目标对象,第二个参数是原对象 ,对原对象中的每个属性进行判断,如果是,那么将他拷贝到目标的对象上去。

    2)在jquery 中的实现:

    jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
    target = arguments[0] || {},
    i = 1,
    length = arguments.length,
    deep = false;
    //如果第一个值为bool值,那么就将第二个参数作为目标参数,同时目标参数从2开始计数
    if ( typeof target === "boolean" ) {
    deep = target;
    target = arguments[1] || {};
    // skip the boolean and the target
    i = 2;
    }
    // 当目标参数不是object 或者不是函数的时候,设置成object类型的
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
    target = {};
    }
    //如果extend只有一个函数的时候,那么将跳出后面的操作
    if ( length === i ) {
    target = this;
    --i;
    }
    for ( ; i < length; i++ ) {
    // 仅处理不是 null/undefined values
    if ( (options = arguments[ i ]) != null ) {
    // 扩展options对象
    for ( name in options ) {
    src = target[ name ];
    copy = options[ name ];
    // 如果目标对象和要拷贝的对象是恒相等的话,那就执行下一个循环。
    if ( target === copy ) {
    continue;
    }
    // 如果我们拷贝的对象是一个对象或者数组的话
    if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
    if ( copyIsArray ) {
    copyIsArray = false;
    clone = src && jQuery.isArray(src) ? src : [];
    } else {
    clone = src && jQuery.isPlainObject(src) ? src : {};
    }
    //不删除目标对象,将目标对象和原对象重新拷贝一份出来。 
    target[ name ] = jQuery.extend( deep, clone, copy );
    // 如果options[name]的不为空,那么将拷贝到目标对象上去。
    } else if ( copy !== undefined ) {
    target[ name ] = copy;
    }
    }
    }
    }
    // 返回修改的目标对象
    return target;

    }; 

    jquery的实现原理和tangram差不多,也是讲原对象的属性分别拷贝到目标对象上去,不过jq可以接受的参数比tangram要多,他可以接受无限和参数,如果第一个参数为true的话,将执行深度拷贝,将原对象和目标对象中的某些属性值合并起来。

     3)protype.js的实现方式

      function extend(destination, source) {
        for (var property in source)
          destination[property] = source[property];
        return destination;

      } 

    也是遍历原 对象的各种属性,然后将他拷贝到目标对象上去。实现的方式和tangram类似。

     4)dojo的实现

    dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
    // summary:
    // Adds all properties and methods of props to constructor's
    // prototype, making them available to all instances created with
    // constructor.
    for(var i=1, l=arguments.length; i<l; i++){
    d._mixin(constructor.prototype, arguments[i]);
    }
    return constructor; // Object

    var extraNames, extraLen, empty = {};
    for(var i in {toString: 1}){ extraNames = []; break; }
    dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
    "propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
    extraLen = extraNames.length;
    dojo._mixin = function(/*Object*/ target, /*Object*/ source){
    // summary:
    // Adds all properties and methods of source to target. This addition
    // is "prototype extension safe", so that instances of objects
    // will not pass along prototype defaults.
    var name, s, i;
    for(name in source){
    // the "tobj" condition avoid copying properties in "source"
    // inherited from Object.prototype.  For example, if target has a custom
    // toString() method, don't overwrite it with the toString() method
    // that source inherited from Object.prototype
    s = source[name];
    //fixed by yupeng 判断元素是否是对象的属性
    if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
    target[name] = s;
    }
    }
    // IE doesn't recognize some custom functions in for..in
    if(extraLen && source){
    for(i = 0; i < extraLen; ++i){
    name = extraNames[i];
    s = source[name];
    if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
    target[name] = s;
    }
    }
    }
    return target; // Object

    dojo首先会封装一个_mixin方法,该方法起到的作用其实就是extend该起到的作用,然后再背部调用_mixin()方法,封装的extend方法可以接受多个参数,同时将原对象的每个属性都拷贝到目标对象的原型方法上。 

    技巧(extend方法的妙用):

    1)实现组件参数的灵活配置,我们在写组件的时候,可以使用一些默认的配置参数,但是如果用户想定制一些特殊的样式的话,可以使用extend方法

    例如在写jq插件的时候

    (function($) { 

    $.fn.xxxx= function(options) {

    var defaults = {
    a: false,
    b: {},
    c: false,
    b: false
    };

    var params = $.extend({}, defaults, options || {}); 

    //接下来对函数进行处理。 

    })(jquery) 

    2)实现类方法的拷贝。 

  • 相关阅读:
    python 【第一篇】初识python
    python 【目录】
    python 爬虫必知必会
    MySQL测试代码
    MySQL学习笔记
    pycharm社区版无database 解决方法
    windows python flask上传文件出现IOError: [Errno 13] Permission denied: 'E:\git\test\static\uploads'的解决方法
    ubuntu下python flask环境搭建
    windows下的python flask环境搭建
    Mockito (十四)
  • 原文地址:https://www.cnblogs.com/yupeng/p/2389997.html
Copyright © 2011-2022 走看看