好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Ember源码学习

Ember源码学习

ember.js是当今最强大的javascript MVC框架。当一把胡子拉碴的大牛人跑进JS界搞这东西时,昭示了JS全盛时期的到来。

可能你听说过javascriptmvc.js这个时期在jQuery支援下赫赫有名的框架,或者现在更为流行的backbone,但相对于ember.js,它们就黯然失色了。不过正由于看上去非常高端,也吓跑了不少人。在富应用日益流行的今天,越来越多工作转到前端了,JS的代码变得非常庞大,如此组织它们是一个难题。如果公司是使用EXT这样的强大UI框架,这可免谈了。但许多公司只能摆弄一下jQuery,jQuery可是堆代码的利器。堆得快,倒得快,这也是其特色。jQuery易入门,因此其开发者龙蛇混杂,当然这是相对于国外来说,国内考虑到成本与中国特色,前端人员的素质是极差的,他们写的jQuery代码是非常难维护的。因此要引入规范与绝束。MVC无疑是当中最可靠的选项。如果大家的业务代码与UI的编写也按MVC的规定来写,所有都有章可循,这维护成本就大大降低。

有人说框架会让程序员变成填空题的码农,MVC这种强约束,让程序员成为了流水线的工人了。农民工只能搞些土产品,但工人可以组装精密仪器。欢欣雀跃吧,前端的码农们!你们现在升级了无产阶级的中流砥柱——流水线工人了!你会明白后端的程序员为什么这么高吧,因为他们早在十年前,在JAVA,C#,C++,JAVA的伟大框架的统治下,实现了农转非!相对于后端的工业国家,前端的国度可怜得像非洲部落酋长国,即使jQuery的现世,只不过让部落民转变成法老的子民。

if ( 'undefined' === typeof Ember) {

 

     Ember = {};

     //暴露到全局作用域下

     if ( 'undefined' !== typeof window) {

         window.Em = window.Ember = Em = Ember;

     }

 

}

Ember.isNamespace = true;

 

Ember.toString = function () {

     return "Ember" ;

};

 

Ember.VERSION = '0.9.8.1' ;

 

Ember.ENV = 'undefined' === typeof ENV ? {} : ENV;

 

//决定是否缓存计算值,可以使用volatile禁止它

Ember.CP_DEFAULT_CACHEABLE = (Ember.ENV.CP_DEFAULT_CACHEABLE !== false);

 

Ember.VIEW_PRESERVES_CONTEXT = (Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);

 

Ember.K = function () {

     return this;

};

//调试相关

 

if ( 'undefined' === typeof Ember.assert) {

     Ember.assert = Ember.K;

}

if ( 'undefined' === typeof Ember.warn) {

     Ember.warn = Ember.K;

}

if ( 'undefined' === typeof Ember.deprecate) {

     Ember.deprecate = Ember.K;

}

if ( 'undefined' === typeof Ember.deprecateFunc) {

     Ember.deprecateFunc = function (_, func) {

         return func;

     };

}

//向前兼容

if ( 'undefined' === typeof ember_assert) {

     window.ember_assert = Ember.K;

}

if ( 'undefined' === typeof ember_warn) {

     window.ember_warn = Ember.K;

}

if ( 'undefined' === typeof ember_deprecate) {

     window.ember_deprecate = Ember.K;

}

if ( 'undefined' === typeof ember_deprecateFunc) {

 

     window.ember_deprecateFunc = function (_, func) {

         return func;

     };

}

//调试相关

Ember.Logger = window.console || {

     log: Ember.K,

     warn: Ember.K,

     error: Ember.K

};

//用于储存一些静态方法与特征偶测的结果

var platform = Ember.platform = {} ;

 

//类工厂,只是Object.create的别名

platform.create = Object.create;

 

if (!platform.create) {

     //向前兼容

     var O_ctor = function () {},

     O_proto = O_ctor.prototype;

 

     platform.create = function (obj, descs) {

         O_ctor.prototype = obj;

         obj = new O_ctor();

         O_ctor.prototype = O_proto;

 

         if (descs !== undefined) {

             for ( var key in descs) {

                 if (!descs.hasOwnProperty(key)) continue ;

                 //第二个参数也进行补完了

                 platform.defineProperty(obj, key, descs[key]);

             }

         }

 

         return obj;

     };

     //标识是赝品

     platform.create.isSimulated = true;

}

 

var defineProperty = Object.defineProperty;

var canRedefineProperties, canDefinePropertyOnDOM;

//IE8的 Object.defineProperty就是半成品,只能处理DOM属性

if (defineProperty) {

     try {

         defineProperty({}, 'a' ,{

             get: function (){}

             });

     } catch (e) {

         /** @private */

         defineProperty = null;

     }

}

//处理其他奇异的BUG

if (defineProperty) {

     // Detects a bug in Android <3.2 where you cannot redefine a property using

     // Object.defineProperty once accessors have already been set.

     /** @private */

     canRedefineProperties = ( function () {

         var obj = {};

 

         defineProperty(obj, 'a' , {

             configurable: true,

             enumerable: true,

             get: function () { },

             set: function () { }

         });

 

         defineProperty(obj, 'a' , {

             configurable: true,

             enumerable: true,

             writable: true,

             value: true

         });

 

         return obj.a === true;

     })();

 

     // This is for Safari 5.0, which supports Object.defineProperty, but not

     // on DOM nodes.

     /** @private */

     canDefinePropertyOnDOM = ( function (){

         try {

             defineProperty(document.createElement( 'div' ), 'definePropertyOnDOM' , {});

             return true;

         } catch (e) { }

 

         return false;

     })();

 

     if (!canRedefineProperties) {

         /** @private */

         defineProperty = null;

     } else if (!canDefinePropertyOnDOM) {

         /** @private */

         defineProperty = function (obj, keyName, desc){

             var isNode;

 

             if (typeof Node === "object" ) {

                 isNode = obj instanceof Node;

             } else {

                 isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string" ;

             }

 

             if (isNode) {

                 // TODO: Should we have a warning here?

                 return (obj[keyName] = desc.value);

             } else {

                 return Object.defineProperty(obj, keyName, desc);

             }

         };

     }

}

 

platform.defineProperty = defineProperty;

 

platform.hasPropertyAccessors = true;

 

if (!platform.defineProperty) {

   platform.hasPropertyAccessors = false;

 

   platform.defineProperty = function (obj, keyName, desc) {

     ember_assert( "property descriptor cannot have `get` or `set` on this platform" , !desc.get && !desc.set);

     obj[keyName] = desc.value; //如果不支持,只能取得这个对象的value进行赋值

   };

 

   platform.defineProperty.isSimulated = true;

}

 

 

// UUID部分

var GUID_KEY = '__ember' + (+ new Date ());

var uuid, numberCache, stringCache;

 

uuid         = 0;

numberCache  = [];

stringCache  = {};

//让其不可遍历

var GUID_DESC = Ember.GUID_DESC = {

   configurable: true,

   writable: true,

   enumerable: false

};

 

var o_defineProperty = Ember.platform.defineProperty;

var o_create = Ember.platform.create;

 

Ember.GUID_KEY = GUID_KEY;

//生成一个UUID

Ember.generateGuid = function (obj, prefix) {

   if (!prefix) prefix = 'ember' ;

   var ret = (prefix + (uuid++));

   if (obj) {

     GUID_DESC.value = ret;

     o_defineProperty(obj, GUID_KEY, GUID_DESC);

     GUID_DESC.value = null;

   }

 

   return ret ;

};

 

//取得每个对象的UUID对应的键名,UUID是用于对象的,因此对于基本数据类型,它们的返回值是规定好的

Ember.guidFor = function (obj) {

 

   // special cases where we don't want to add a key to object

   if (obj === undefined) return "(undefined)" ;

   if (obj === null) return "(null)" ;

 

   var cache, ret;

   var type = typeof obj;

 

   switch (type) {

     case 'number' : //处理不可变对象

       ret = numberCache[obj];

       if (!ret) ret = numberCache[obj] = 'nu' +obj;

       return ret;

 

     case 'string' : //处理不可变对象

       ret = stringCache[obj];

       if (!ret) ret = stringCache[obj] = 'st' +(uuid++);

       return ret;

 

     case 'boolean' : //处理不可变对象

       return obj ? '(true)' : '(false)' ;

 

     default :

       if (obj[GUID_KEY]) return obj[GUID_KEY];

       if (obj === Object) return '(Object)' ; //跳过原生对象的构造器

       if (obj === Array)  return '(Array)' ; //跳过原生对象的构造器

       return Ember.generateGuid(obj, 'ember' );

   }

};

//元

var META_DESC = { //其特性描述

   writable:    true,

   configurable: false,

   enumerable:  false,

   value: null

};

 

var META_KEY = Ember.GUID_KEY+ '_meta' ;

 

Ember.META_KEY = META_KEY;

 

// Placeholder for non-writable metas.

var EMPTY_META = { //空元

   descs: {},

   watching: {}

};

 

if (Object.freeze) Object.freeze(EMPTY_META);

 

var createMeta = Ember.platform.defineProperty.isSimulated ? o_create : ( function (meta) { return meta; });

 

 

Ember.meta = function meta(obj, writable) {

 

   var ret = obj[META_KEY];

   if (writable===false) return ret || EMPTY_META; //如何不可写,直接返回或返回空元

 

   if (!ret) { //如果此对象刚刚设置

     o_defineProperty(obj, META_KEY, META_DESC);

     ret = obj[META_KEY] = createMeta({

       descs: {},

       watching: {},

       values: {},

       lastSetValues: {},

       cache:  {},

       source: obj

     });

 

     // make sure we don't accidentally try to create constructor like desc

     ret.descs.constructor = null;

 

   } else if (ret.source !== obj) {

     ret = o_create(ret); //复制

     ret.descs    = o_create(ret.descs); //复制

     ret.values   = o_create(ret.values); //复制

     ret.watching = o_create(ret.watching); //复制

     ret.lastSetValues = {};

     ret.cache    = {};

     ret.source   = obj;

 

     o_defineProperty(obj, META_KEY, META_DESC);

     ret = obj[META_KEY] = createMeta(ret);

   }

   return ret;

};

//取得对象的某些元信息

Ember.getMeta = function getMeta(obj, property) {

   var meta = Ember.meta(obj, false);

   return meta[property];

};

 

Ember.setMeta = function setMeta(obj, property, value) {

   var meta = Ember.meta(obj, true);

   meta[property] = value;

   return value;

};

Ember.metaPath = function (obj, path, writable) {

   var meta = Ember.meta(obj, writable), keyName, value;

 

   for ( var i=0, l=path.length; i<l; i++) {

     keyName = path[i];

     value = meta[keyName];

 

     if (!value) {

       if (!writable) { return undefined; }

       value = meta[keyName] = { __ember_source__: obj };

     } else if (value.__ember_source__ !== obj) {

       if (!writable) { return undefined; }

       value = meta[keyName] = o_create(value);

       value.__ember_source__ = obj;

     }

 

     meta = value;

   }

 

   return value;

};

 

Ember.wrap = function (func, superFunc) {

 

   function K() {}

 

   var newFunc = function () {

     var ret, sup = this._super;

     this._super = superFunc || K;

     ret = func.apply(this, arguments);

     this._super = sup;

     return ret;

   };

 

   newFunc.base = func;

   return newFunc;

};

//用于判定是否为类数组

mber.isArray = function (obj) {

   if (!obj || obj.setInterval) { return false; }

   if (Array.isArray && Array.isArray(obj)) { return true; }

   if (Ember.Array && Ember.Array.detect(obj)) { return true; }

   if ((obj.length !== undefined) && 'object' ===typeof obj) { return true; }

   return false;

};

//将一切转换为数组

//      Ember.makeArray();          => []

//      Ember.makeArray(null);      => []

//      Ember.makeArray(undefined); => []

//      Ember.makeArray('lindsay'); => ['lindsay']

//      Ember.makeArray([1,2,42]);  => [1,2,42]

Ember.makeArray = function (obj) {

   if (obj === null || obj === undefined) return [];

   return Ember.isArray(obj) ? obj : [obj];

};

本篇到此为止,只是知道它费了很大劲模拟Object.defineProperties,与搞了个META机制,暂时不知有什么用。

 

 

标签:  javascript ,  ember.js

作者: Leo_wl

    

出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Ember源码学习的详细内容...

  阅读:43次