>  기사  >  웹 프론트엔드  >  JavaScript 프레임워크 디자인 시드 module_javascript 기술

JavaScript 프레임워크 디자인 시드 module_javascript 기술

WBOY
WBOY원래의
2016-05-16 15:53:331051검색

시드 모듈은 프레임워크의 첫 번째 실행 부분인 코어 모듈이라고도 합니다. jQuery와 같은 단일 파일 함수 라이브러리도 여러 개의 내부 모듈로 나누어져 있는데, 일부 모듈은 실행 시 바로 앞에서 실행되어야 하고, 일부 모듈은 사용할 때만 실행됩니다. 일부 모듈은 필요하지 않고, 존재감이 약하며, 특정 브라우저에서만 실행될 수 있습니다.

시드 모듈은 그 안에 포함된 방법이 반드시 완벽하게 기능하고 잘 설계될 필요는 없지만 확장성이 뛰어나고 일반적으로 사용되며 안정적이어야 합니다.

확장성은 이를 통해 다른 모듈을 포함할 수 있음을 의미하며, 공통 사용은 대부분의 모듈을 사용하여 작업의 중복을 방지할 수 있음을 의미합니다. 안정성은 버전 반복 중에 새로운 방법으로 쉽게 대체되지 않음을 의미합니다.

많은 프레임워크와 라이브러리의 구현을 참조하면 시드 모듈에는 객체 확장, 배열, 유형 결정, 단순 바인딩 및 언로드, 충돌 없는 처리, 모듈 로딩 및 domReady 기능이 포함되어 있다고 믿습니다. 이 장은 대량 프레임워크 시드 모듈이 템플릿입니다.

https://github.com/RubyLouvre/mass-Framework

1. 네임스페이스

프레임워크의 초기 부분인 시드 모듈은 글로벌 인프라 구축을 지원하는 역할을 담당합니다. jQuery는 IIFE(즉시 호출되는 함수 표현식)를 사용하여 시작하기 좋습니다.

LIFE는 현대 JavaScript 프레임워크에서 가장 중요한 인프라로, 다양한 오염을 방지하기 위해 자신을 세포처럼 포장합니다. 프로토타입, mootools와 같은 발판과 마찬가지로 프레임워크의 존재감을 느낄 수 없게 만드는 네임스페이스이며, javascript, DOM, BOM 등 전체 실행 환경 구석구석에 그 중요성이 미치게 됩니다. , 네이티브에 지대한 영향을 미칩니다. 객체 프로토타입을 확장할 수 있습니다. Douglas(JSON 작성자)의 강력한 반대 때문에 새로운 프레임워크가 네임스페이스를 기반으로 구축되었습니다.

자바스크립트에서 네임스페이스를 시뮬레이션하는 방법을 살펴보겠습니다. 자바스크립트는 모두 객체를 기반으로 하지만 함수, RegExp, 객체 등 해당 유형을 충족하는 객체만이 요구 사항을 충족할 수 있지만 가장 일반적으로 사용되는 것은 객체와 함수입니다. 객체에 속성을 추가하면 이 속성이 객체가 됩니다. 이런 방식으로 프레임워크를 질서 있게 구축할 수 있습니다. 사용자가 메소드를 호출하려면 xxx.yyy.zzz() 형식으로 호출하면 됩니다.

  if( typeof(Ten) === "undefined" ){
    Ten = {};
    Ten.Function = { /*略*/ }
    Ten.Array = { /*略*/ }
    Ten.Class = { /*略*/ }
    Ten.JSONP = new Ten.Class(/*略*/ )
    Ten.XHR = new Ten.Class(/*略*/ )
  }

주요 라이브러리의 구현을 살펴보면 기본적으로 Base2의 Base, Ext의 Ext, jQuery의 jQuery, YUI의 YUI, dojo의 dojo, MochiKit용 mochKit과 같이 처음에 전역 변수를 네임스페이스로 정의한 후 이를 확장합니다. . 전역 변수의 오염 정도의 관점에서 두 가지 범주로 나뉩니다.

prototype.js와 mootools는 Base2와 동일한 카테고리로 분류됩니다. Prototype의 철학은 javascript의 기본 객체를 확장하는 것입니다. 초기에는 프로토타입이 사실상의 표준이라고 불릴 정도였습니다. 따라서 다른 라이브러리와의 공존 문제는 고려되지 않습니다. Basic Prototype은 script.aculo.us, rico, Plotr, protoChart, Script2 및 대규모 유료 플러그인 카테고리와 같은 우수한 클래스 라이브러리도 개발했습니다. 또한, 일부 출처를 가진 거의 모든 플러그인은 lightBox와 같이 Prototype과 관련되어 있습니다. mootools는 프로토타입.js의 업그레이드 버전으로, OO에 더 가깝고 API를 완전히 복제합니다. Base2는 IE 버그를 수정하고 IE에 표준 브라우저 API를 제공하기를 원하므로 모든 기본 개체도 오염시킵니다.

두 번째 범주는 jQuery, YUI 및 EXT 프레임워크입니다. YUI 및 Ext는 객체 내에 객체를 중첩하여 구축됩니다. jQuery는 다른 접근 방식을 취합니다. 선택기 지향적이므로 네임스페이스는 사용자가 CSS 표현기의 문자열을 쉽게 전달할 수 있도록 하는 기능입니다. 그런 다음 선택기를 통해 검색하고 마지막으로 jQuery 개체 인스턴스를 반환합니다.

jQuery는 초기에 Prototype과 같이 $를 네임스페이스로 사용했기 때문에 많은 라이브러리의 공존 메커니즘을 구현했습니다. jQuery의 다중 라이브러리 공존 원리는 매우 간단하므로 나중에는 이렇게 되었습니다. Xiaoku를 위한 많은 라이브러리의 공존 메커니즘. 먼저, 네임스페이스를 임시 변수에 저장한 다음(이 개체는 현재 자체 프레임워크의 일부가 아니며, 프로토타입.js 또는 다른 개체일 수 있음) noConstrict를 사용하여 다시 저장합니다.

  //jQuery1.2
  var _jQuery = window.jQury , _$ = window.$; //把可能存在同名变量先保存起来
  jQury.extend({
    noConflict : function(deep) {
      window.$ = _$; //这时再放回去
      if (deep) //补充 if ( deep && window.jQuery === jQuery )
        window.jQury = _jQuery;
      return jQury;
    }
  })

참고: http://zhidao.baidu.com/question/1239712776390687219.html

그러나 jQuery의 noConstrict는 단일 파일 클래스 라이브러리 프레임워크에만 유용하며 Ext.처럼 복사할 수 없습니다. 따라서 네임스페이스 이름을 변경한 후 Ext를 null로 설정한 다음 동적 로딩을 통해 새 javascript 파일에 도입하면 해당 파일이 Ext로 호출되므로 오류가 발생합니다.

2. 객체 확장

네임스페이스에 새로운 기능을 추가하려면 메커니즘이 필요합니다. 이 메서드는 일반적으로 JavaScript에서 확장 또는 혼합이라고 합니다. 속성 설명자(Property Descriptor)가 탄생하기 전에는 JavaScript 개체가 원하는 대로 멤버를 추가, 변경, 삭제할 수 있었기 때문에 개체를 확장하는 것이 매우 편리합니다. 간단한 확장 메서드 구현은 다음과 같습니다.

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

不过,旧版本IE在这里有个问题,它认为像Object的原型方法就是不应该被遍历出来,因此for in循环是无法遍历valueOf、toString的属性名。这导致,模拟Object.keys方法是现实时也遇到了这个问题。

  Object.keys = Object.keys || function(obj){
    var a = [];
    for(a[a.length] in obj);
    return a;
  }

在不同的框架,这个方法还有不同的实现,如Ext分别为apply与applyIf两个方法,前者会覆盖目标对象的同名属性,而后者不会。dojo允许多个对象合并在一起。jQuery还支持深拷贝。下面是mass Farmework的mix方法。支持多对象合并与选择是否覆写。

  function mix(target,source){ //如果最后参数是布尔,判定是否覆盖同名属性
    var args = [].slice.call(arguments), i = 1, key,
      ride = typeof args[args.length - 1] == "boolean" ? args.pop() : true;
    if (args.length === 1){ //处理$.mix(hash)的情形
      target = !this.window ? this : {};
      i = 0;
    }  
    while ((source = args[i++])) {
      for (key in source){ //允许对象糅杂,用户保证都是对象
        if (ride || !(key in target)) {
          target[key] = source[key];
        }
      }
    }
    return target;
  }

3.数组化

浏览器下存在很多类数组对象,如function内的arguments,通过document.forms、form.elements,document.links、select.options、document.getElementsByName,document.getElementsByTagName、childNodes、children等方式获取的节点的结合(HTMLCollection 、NodeList)或按照某些特殊的写法自定义对象。

类数组对象是一个很好的存储结构。不过功能太弱了,为了能使用纯数组的那些便捷的方法,我们会在处理它们前都会做一下转换。

通常来说,使用[].slice.call就能转换了 ,不过功能不够用,但在旧版本的HTMLCollection、NodeList不是Object的子类,采用如上的方法会导致IE执行异常。我们看一下

jQuery:makeArray

  var makeArray = function(array) {
    var ret = [] ;
    if(array != null){
      var i = array.length;
      if(i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval)
        ret[0] = array;
      else
        while (i)
          ret(--i) = array[i];
    }
    return ret;
  }

mass的实现,一开始就进行区分,直接[].slice.call,IE的话自己动手实现一个slice方法

  $.slice = window.dispatchEvent ? function(nodes,start,end){
    return [].slice.call(nodes,start,end);
  } : function (nodes,start,end){
    var ret = [],
       n = nodes.length;
    if (end === void 0 || typeof end === "number" && isFinite(end)){
      start = parseInt (start,0) || 0;
      end = end == void 0 ? n:parseInt (end,10);
      if(start < 0){
        start += n;
      }
      if (end > n) {
        end =n
      };
      if (end < 0) {
        end += n
      };
      for (var i = start; i < end; ++i){
        ret[i-start] = nodes[i];
      }
    }
    return ret;
  }

4.类型的判定

javascript存在两套类型系统,一套是基本的数据类型,另一套是对象类型系统。基本数据类型包括6中 。分别是undefined、string、null、boolean、function、object。基本数据类型是通过typeof来检测的。对象类型系统是以基础类型系统为基础的,通过instanceof来检测的。然而,javascript自带的这两套识别机制非常不靠谱,于是就催生了isXXX系列。就拿typeof来说,它只能粗略识别出string、number、boolearn、function、undefined、object这6种数据类型,无法识别null,RegExpArgument等细分的对象类型。

  typeof null // => "object"
  typeof document.childNodes //=> safari: "function"
  typeof document.creatElement('embed') //=> ff3-10 "function"
  typeof document.creatElement('object') //=> ff3-10 "function"
  typeof document.creatElement('object') //=> ff3-10 "function"
  typeof /\d/i //在实现了ecma262v4的浏览器返回"function"
  typeof window.alert //ie678 "object"
  var iframe = document.creatElement("iframe")
  document.body.appendChild(iframe)
  xArray = window.frames[window.frames.length - 1].Array;
  var arr = new xArray(1,2,3) //=>[1,2,3]
  arr instanceof Array ;// false
  isNaN("aaa") //=> true

另外,以前人们总是以document.all来判断是否为ie,这其实是很危险的,因为,用document.all来取得页面中所有的元素是不错的注意,这个方法FF,chrome打算使用很久了,不过人们都这样判断,就是在chrome下有这样的闹剧。

  typeof document.all //undefined
  document.all //HTMLAllCollection [728] (728为元素总数)

在判定undefined、null、string、number、boolean、function这六个还算简单,前面两个可以分别与void(0)、null比较,后面4个的typeof也可以满足90%的情形。这样说是因为string、number、boolean可以包装成伪对象。

  typeof new Boolean(1); //=>"object"
  typeof new Number(1); //=>"object"
  typeof new String("aa"); //=> "object"

这些还不是最难的,难点在于RegExp与Array.判定RegExp的情况很少。Array则不一样。有关isArray的实现不下二十种。都是因为鸭式辨型被打破了。直到prototype.js把Object.prototype.toString发掘出来。此方法是直接输出内部的[[Class]],绝对精准。有了它,95%的陷阱被跳过了。

  function isArray(arr){
    return arr instanceof Array;
  }

  function isArray(arr){
    return !!arr && arr.constructor === Array;
  }

  function isArray(arr) { //prototype.js 1.6
    return arr != null && typeof arr === "object" && 'splice' in arr && 'join' in arr;
  }

  function isArray(arr){// Douglas Crockford(JSON作者,反对原型污染)
    return typeof arr.sort == "function"
  }

  function isArray(array){ //kriszyp
    var result = false;
    try{
      new array.constructor (Math.pow(2,32))
    } catch (e){
      result = /Array/.test(e.message)
    }
    return result;
  };

  function isArray(o){//kangax
    try{
      Array.prototype.toString.call(o);
      return true;
    } catch (e) {
    }
    return false;
  }

  function isArray(o){ //kangax
    if(o && typeof o == 'object' && typeof o.length == 'number' && isFinite(o.length))
    {
      var _origLength = o.length;
      o[o.length] = '__test__';
      var _newLength = o.length;
      o.length = _origLength;
      return _newLength == _origLength + 1;
    }
    return false
  }

至于null 、 undefined 、NaN直接这样写

  function isNaN(obj) {
    return obj !== obj
  }

  function isNull(obj) {
    return obj === null;
  }

  function isUndefined(obj){
    return obj === void 0;
  }

最后要判定的是对象是window,由于ECMA是不规范的Host对象,window对象属于host.所以也就没有被约定。就算Object.prototype.toString也对它没办法

  [object Object] IE6 
  [object Object] IE7 
  [object Object] IE8
  [object Window] IE9
  [object Window] ff3.6
  [object Window] opera10
  [object DOMWindow] safari 4.04
  [object global] chrome5.0

不过根据window.window和window.setInterval去判定更加不靠谱,用一个技巧就可以完美识别ie6 ie7 ie8的window对象,其它还用toString,这个神奇的hack就是,window与document互相比较,如果顺序不一样,结果也是不一样的!

剩下的就是一些经典方法:

在prototype.js中,拥有isElement,isArray,isHash,isFunctoion,isString,isNumber,isDate,isUndefined。

mootools有一个typeOf判定基本类型,instanceOf判定自定义“类”

RightJS 有isFunction , isHash , isString , isNumber , isArray ,isElement, isNode.

Ext有比较全面的判断,isEmpty,isArray,isDate,isObject,isSimpleObject,isPrimitive,isFunction,isNumber,isMumeric,isString,isBoolean,isElement,isTextNode,isDefined,isIterable,应有尽有。最后,还有typeOf判断基本类型。

Underscore.js有isElement,isEmpty,isArray,isArgument,isObject,isFunction,isString,isNumber,isFinite,isNaN,isBoolean,isDate,isRegExp,isNull,isUndefined.

jQuery就不与其它框架一样了,在jQuery1.4中只有isFunction,isArray,isPlainObject,isEmptyObject。isFunction,isArray用户肯定用的较多,isPlainObject是用来判断是否是纯净的js对象。既不是DOM,BOM对象,也不是自定义的“类”的实例对象,制造它的目的最初是为了深拷贝,避开像window那样自己引用自己的对象。isEmptyObject是用于数据缓存的系统,当此对象为空时,就可以删除它。

  //jQuery2.0纯净数组的判定思路
  jQuery.isPlainObject = function(obj){
    //首先排除基础类型不为Object的类型,然后是DOM节点与window对象
    if(jQuery.type(obj) !== "object" || object.nodeType || jQuery.isWindow(obj)){
      return false;
    }

    //然后回溯它的最近的原型对象是否有isPrototypeOf.
    //旧版本的IE一些原生的对象没有暴露constructor、prototype。因此在这里过滤掉
    try{
      if (obj.constructor && !hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){
        return false;
      }
    } case(e) {
      return false;
    }
    return true;
  }

avalon.mobile中有一个更精简的版本,只支持最新的浏览器,可以大胆的使用ecma262v5新API

  avalon.isPlainObject = function(obj){
    return obj && typeof obj === "object" && Object.getPrototypeOf(obj) === Object.prototype
  }

isArrayLike也是一个常用的方法,但是判定一个类数组太难了,唯一的识别方法就是判断有一个大于0或等于0的length属性,此外,还有一些共识,如window与函数和元素节点,如(form元素),不算类数组,虽然它们都满足前面的条件。因此,至今jQuery都没有把它暴露出来。

  //jQuery2.0
  function isArrayLike(obj){
    var length = obj.length , type = jQuery.type(obj);
    if (jQuery.isWindow(obj)){
      return false;
    }
    if (obj.nodeType === 1 && length){
      return true
    }
    return type === "array" || type !== "function" && (length === 0 || typeof length === "number" && length > 0 && (length -1) in obj);
  }

  // avalonjs
  function isArrayLike (obj) {
    if (obj && typeof obj === "object"){
      var n = obj.length
      if (+n === n && !( n % 1) && n >= 0){//检测length是否为非负整数
        try{
          if ({}.prototypeIsEnumerable.call(obj,'length') === false){
          return Array.isArray(obj) || /^\s&#63;function/.test(obj.item || obj.callee)
         }
        return true;
       } catch (e) { //IE的NodeList直接报错
        return true;
       }
      }
    }
  return false
  }

在Prototype.js1.3版本中的研究成果(Object.prototype.toString.call)就应用于jQuery,在jQuery1.2中,判断一个变量是否为函数非常复杂。

复制代码 代码如下:

    isFunction : function(fn){
        return !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test(fn + "");
    }

jQuery1.43中引入isWindow来处理makeArray中对window的判定,引入isNaN用于确保样式赋值的安全。同时引入type代替typeof关键字,用于获取基本数据的基本类型。

  class2type = {};
  jQuery.each("Boolean Number String Function Array Date RegExpObject".split(" "),function( i , name ){
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
  });

  jQuery.type = function(obj){
    return obj == null &#63; String(obj) : class2type[toString.call(obj)] || "object";
  }

jQuery1.7中添加isNumeric代替isNaN。这是个不同于其它框架的isNumber,它可以是个字符串,只要外观上像数字就可以了。但jQuery1.7还做了一个违背之前提到稳定性的事情。冒然去掉jQuery.isNaN,因此,基于旧版jQuery的有大批插件失效。

  //jQuery.1.43-1.64
  jQuery.isNaN = function ( obj ) {
    return obj == null || !rdigit.test( obj ) || isNaN( obj );
  }

  //jQuery1.7就是isNaN的去反版
  jQuery.isNumeric = function ( obj ) {
    return obj != null && rdigit.test( obj ) && !isNaN( obj );
  }

  //jQuery.1.71 - 1.72
  jQuery.isNumeric = function ( obj ) {
    return !isNaN( parseFloat(obj) ) && isFinite( obj );
  }

  //jQuery2.1
  jQuery.isMumeric = function( obj ) {
    return obj - parseFloat(obj) >= 0;
  }

massFarmeWork的思路与jQuery一致,尽量减少isXXX系列的代码,把is Window,isNaN,nodeName等方法做了整合。代码较长,既可以获取类型,也可以传入第二参数进行类型比较。

  var class2type = {
    "[objectHTMLDocument]" : "Document",
    "[objectHTMLCollection]" : "NodeList",
    "[objectStaticNodeList]" : "NodeList",
    "[objectIXMLDOMNodeList]" : "NodeList",
    "[objectDOMWindow]" : "window",
    "[object global]" : "window",
    "Null" : "Null",
    "undefined" : "undefined"
  },
  toString = class2type.toString;
  "Boolean,Number,String,Function,Array,Date,RegExp,Window,Document,Arguments,NodeList".replace($.rword,function( name ) {
    class2type[ "[object" + name + "]" ] = name;
  });

  //class2type这个映射几乎把常用的判定对象一网打尽
  mass.type = function( obj , str ){
    var result = class2type[ (obj == null || obj !== obj) &#63; obj : toString.call(obj) ] || obj.nodeName || "#";
    if(result.charAt(0) === "#") { //兼容旧版浏览器的个别情况,如window.opera
      //利用IE678 window === document为true,document === window为false
      if( obj == obj.document && obj.document != obj ) {
        result = "window"; //返回构造器名称
      } else if ( obj.nodeType === 9 ) {
        result = "Document";
      } else if ( obj.callee) {
        result = "Arguments";
      } else if ( isFinite(obj.length) && obj.item ) {
        result = "NodeList" //处理节点集合
      } else {
        result = toString.call(obj).slice(8,-1);
      }
    }
    if(str){
      result str === result;
    }
    return result;
  }

然后type方法就十分轻松了,用toSring.call(obj)得出值的左键,直接从映射中取得。IE678,我们才费一些周折处理window,document,argument,nodeList等对象。

百度的七巧板基于实用主义,判定也十分严谨。与EXT一样,能想到的写上,并且判定十分严谨。

目前版本2.0.2.5 http://tangram.baidu.com/api#baidu.type()

  baidu.isDate = function( unknow ) {
  return baidu.type(unknow) == "date" && unknow.toString() != 'Invalid Date' && !isNaN(unknow);
  };
  baidu.isNumber = function( unknow ) {
  return baidu.type(unknow) == "number" && isFinite( unknow );
  };

 5.主流框架的引入机制-domReady

domReady其实是一种名为"DOMContentLoaded"事件的别称,不过由于框架的需要,它与真正的DOMContentLoaded有一点区别,在很多新手和旧的书中,很多人将其写在window.onload回调中,防止dom树还没有建完就开始对节点操作。而对于框架来说,越早越介入dom就越好,如要进行特征侦测之类的。domready还可以满足用户提前绑定事件需求,因为有时页面图片过多等,window.onload事件迟迟不能触发,这时用户操作都没有效果,因此,主流的框架都引入了domReady机制,并且费了很大周折才兼容所有浏览器。具体的策略如下:

对于支持DOMContentLoaded事件使用DOMcontentLoaded事件
旧版本IE使用Diego perini发现的著名Hack

  //by Diego Perini 2007.10.5
   function IEContentLoaded (w, fn) {
   var d = w.document, done = false,
   // 只执行一次用户的回调函数init()
   init = function () {
    if (!done) {
      done = true;
      fn();
    }
   };
  (function () {
    try {
      // DOM树未创建完之前调用doScroll会抛出错误
      d.documentElement.doScroll('left');
    } catch (e) {
      //延迟再试一次~
      setTimeout(arguments.callee, 50);
      return;
    }
    // 没有错误就表示DOM树创建完毕,然后立马执行用户回调
    init();
         })();
  //监听document的加载状态
  d.onreadystatechange = function() {
    // 如果用户是在domReady之后绑定的函数,就立马执行
    if (d.readyState == 'complete') {
      d.onreadystatechange = null;
      init();
    }
       };
  }

此外,IE还可以通过script defer hack进行判定

   document.write("<script id=__ie_onload defer src=//0 mce_src=http://0></scr"+"ipt>"); 
    script = document.getElementById("__ie_onload"); 
    script.onreadystatechange = function() { //IE即使是死链也能触发事件 
          if (this.readyState == "complete") 
    init(); // 指定了defer的script在dom树建完才触发
  }; 

不过还有个问题,如果我们的种子模块是动态加载的,在它插入dom树时,DOM树是否已经建完呢?这该怎么触发ready回调?jQuery的方案是,连onload也监听了 ,但如果连onload也没赶上,就判定document.readyState等于complete。(完美)可惜ff3.6之前没有这属性,看mass的方案

  var readyList = [];
  mess.ready = function( fn ) {
    if ( readyList ) {
      fn.push( fn );
    } else {
      fn();
    }
  }
  var readyFn ,ready = W3C &#63; "DOMContentLoaded" : "readyStatechange";
  function fireReady() {
    for (var i = 0 , fn; fn = readyList[i++]) {
      fn();
    }
    readyList = null;
    fireReady = $.noop; //惰性函数,防止IE9调用_checkDeps
  }
  function doScrollCheck() {
    try { //IE下通过doScrollCheck检测DOM树是否建设完
      html.doScroll("left");
      fireReady();
    } catch (e){
      setTimeout(doScrollCheck);
    }
  }

  //FF3.6前,没有readyState属性
  if (!document.readyState){
    var readyState = document.readyState = document.body &#63; "complete" : "loading";
    if (document.readyState === "complete") {
      fireReady(); //如果在domReay之外加载
    } else {
      $.bind(document,ready,readyFn = function(){
        if(W3C || document.readyState === "complete") {
          fireReady();
          if(readyState){ //IE下不能该项document.readyState
            document.readyState = "complete";
          }
        }
      });
      if (html.doScroll){
        try {//如果跨域就报错,证明有两个窗口
          if (self.eval === parent.eval) {
            doScrollCheck();
          }
        } catch (e) {
          doScrollCheck();
        }
      }
    }

  }

6.无冲突处理

无冲突处理也叫多库共存,$是这个重要的函数名,以至于大家都爱拿它来做自己的命名空间,当jQuery开始发展时,Prototype是主流,jQuery发明了noConflict函数

  var window = this,
  undefined,
  _jQuery = window.jQuery,
  _$ = window.$,
  //将window存入闭包中的同名变量,方便内部函数调用windows不用太麻烦查找它。
  //_jQuery与_$用于以后重写
  jQuery = window.jQuery = window.$ = function(selector, context){
    //用于返回一个jQuery对象
    return new jQuery.fn.init(selector,context);
  }

  jQuery.extend({
    noConflict : function(deep) {
      //引入jQuery类库后,闭包外边的window.$与window.jQuery都储存着一个函数
      //它是用来生成jQuery对象或在domReady后执行里面的函数
      //回顾最上面的代码,在还没有把function赋值给它们时,_jQuery和_$已经被赋值了,因此,它们两的值必然是undefined
      //因此,这种放弃控制权的技术很简单,就是用undefined把window.$里边jQuery函数清除掉。
      //这时,prototype或mootools的$就被拿走了
      window.$ = _$; //相当于window.$ = undefined,如果你有一个叫jQuery的库,也能大方的过渡出去。
      //这时,需要给noConflict添加一个布尔值,true
    
    if (deep)
      //但我们必须使用一个东西接纳jQuery与jQuey的入口函数
      //闭包里边的东西除非被window等宿主引用,否则是不可见的
      //因此,我们把闭包里的jQuery return出去,外面用一个变量接纳就可以
      window.jQuery = _jQuery; //相当window.jQuery = undefined
    return jQuery;
    }
  })

使用时,先引入别人的库,然后引入jQuery,使用调用$.noConflict()进行改名,这样就不影响别人的$运行了。

mass的操作方式是在script标签上定义一个nick属性,那么释放出来的命名空间就是你的那个属性值。里面实现了类似jQuery的机制。

<script nike="aaa" src="mass.js"></script>
<script>
  aaa.log("xxxxxx")
</script>

以上所述就是本文的全部内容了,希望大家能够喜欢。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.