首页 > 代码库 > JQuery源码解析-JQuery的工具方法(3)

JQuery源码解析-JQuery的工具方法(3)

 这篇文章主要对下面这几个方法进行解释

  error();抛出异常

  parseHTML():解析节点

  parseJSON():解析JSON

  parseXML:解析XML

  noop():空函数

  globalEval():全局解析JS

  camelCase():转驼峰

  nodeName():是否为指定节点(内部)

error:方法:

error方法的作用是抛出一个自定义异常,内部直接调用了原生解释的throw new Error

error: function( msg ) {        throw new Error( msg );    },

parseHTML:方法

这个方法是将字符串转成html节点数组,例如:

        var str = "<li>1</li><li>2</li>";        var arr = $.parseHTML(str, document, false);        console.log(arr);

看下源码:

// data: string of html    // context (optional): If specified, the fragment will be created in this context, defaults to document    // keepScripts (optional): If true, will include scripts passed in the html string    parseHTML: function( data, context, keepScripts ) {        if ( !data || typeof data !== "string" ) {            return null;        }        if ( typeof context === "boolean" ) {            keepScripts = context;            context = false;        }        context = context || document;        var parsed = rsingleTag.exec( data ),            scripts = !keepScripts && [];        // Single tag        if ( parsed ) {            return [ context.createElement( parsed[1] ) ];        }        parsed = jQuery.buildFragment( [ data ], context, scripts );        if ( scripts ) {            jQuery( scripts ).remove();        }        return jQuery.merge( [], parsed.childNodes );    },

首先第一个if是对参数进行判断,第二个if是对参数进行处理,如果第二个参数为bool类型的时候,把执行上下文赋值成document,

var parsed = rsingleTag.exec( data ),

这个句话是匹配单标签的,如果是标签,则直接用document.createElement方法创建就可以了。

接下来对第三个参数进行判断,也就是是否可以加载script标签:

scripts = !keepScripts && [];

如果传入为false的话,则给一个空数组,如果为true,scripts则为false

// Single tag        if ( parsed ) {            return [ context.createElement( parsed[1] ) ];        }        parsed = jQuery.buildFragment( [ data ], context, scripts );

这段先对单标签进行处理,如果是多标签,则调用buildFragment方法进行处理。这个方法以后会说到。

    if ( scripts ) {            jQuery( scripts ).remove();        }        return jQuery.merge( [], parsed.childNodes );

如果script不为false的话,则将script标签移除,最后通过merge方法,将其转换成数组。

技术分享

 

 

 

parseJSON:方法,

这个方法是将标准的json字符串转换为json对象,例如:

       var str = ‘{"Name":"jam"}‘;        console.log($.parseJSON(str).Name); //jam 

源码:

parseJSON: JSON.parse,

源码内部直接调用了原生的方法。

parseXML:方法

这个方法是将xml字符串转换为xml节点的,源码如下:

// Cross-browser xml parsing    parseXML: function( data ) {        var xml, tmp;        if ( !data || typeof data !== "string" ) {            return null;        }        // Support: IE9        try {            tmp = new DOMParser();            xml = tmp.parseFromString( data , "text/xml" );        } catch ( e ) {            xml = undefined;        }        if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {            jQuery.error( "Invalid XML: " + data );        }        return xml;    },

先对参数进行判断,然后用了一个try catch ,这个try catch 主要是对Ie9进行支持的,因为在ie9中,如果传入的xml字符串不合法的话,那么在ie9中直接报错,其他浏览器则不会报错,直接返回一个parseerror的节点,所以用try进行处理,

另外DOMParser方法,现在的大部分浏览器都支持,iE8及以下不支持,所以这里进行转换,直接是调用这个方法进行转换的。

最后进行判断,如果报错,则抛出错误信息。

noop:方法

这个方法就是一个空方法,源码:

noop: function() {},

这个空方法在做插件扩展的时候可能会用到。例如:

        function Sa() {            this.default = {                fun:$.noop()            }        }        Sa.prototype.init = function (opt) {            $.extend(this.default, opt);        }

有是在给默认属性的时候,会用到空方法,所以大部分的应用是做这个的。

源码:

noop: function() {},

globalEval:方法

这个方法是创建全局变量的,例如:

        function test() {            eval(‘var a=5‘);            console.log(a); //5;            $.globalEval(‘var b=7‘);            console.log(b); //7;        }        test();        console.log(a); //aught ReferenceError: a is not defined;        console.log(b); //7;

可以看到通过一般的eval进行声明的,只是声明了局部变量,而通过jQuery,则在声明的是全局变量。源码如下:

// Evaluates a script in a global context    globalEval: function( code ) {        var script,                indirect = eval;        code = jQuery.trim( code );        if ( code ) {            // If the code includes a valid, prologue position            // strict mode pragma, execute code by injecting a            // script tag into the document.            if ( code.indexOf("use strict") === 1 ) {                script = document.createElement("script");                script.text = code;                document.head.appendChild( script ).parentNode.removeChild( script );            } else {            // Otherwise, avoid the DOM node creation, insertion            // and removal by using an indirect global eval                indirect( code );            }        }    },

先对参数进行去空格,然后进行判断是否在严格模式下运行,因为严格模式是禁止用eval方法的,当为严格模式的时候,可以看到,内部其实是在head中添加了一个script标签,把传入的代码附加到里面,进行声明之后,在将这个script标签移除,

这样声明的变量就存在全局作用域中了,如果非严格模式下,直接用eval方法进行解析就可以了,但是这里可以看到这个细节,将eval赋值给了声明的变量indirect中,这样做是因为eval有两种,一种是关键字,一种是window下的属性,这样赋值

就是代表调用的window下的属性方法,所以在全局都可以找到,如果只用eval进行解析,那么就会认为是关键字,自然就是局部变量了。

camelCase方法:

这个方法是将传入的参数进行驼峰转换的,因为在代码中并不能对margin-top这种新式的属性进行解析,将margin-top转换为:marginTop这种形式:

        var str = ‘margin-top‘;        console.log($.camelCase(str)); //marginTop

源码如下:

// Convert dashed to camelCase; used by the css and data modules    // Microsoft forgot to hump their vendor prefix (#9572)    camelCase: function( string ) {        return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );    },

代码中可以看到第一个replace是对ms进行处理,RMSPrefix正则是对-ms-进行匹配,将-ms-替换成ms- 这样在进行转换就可以了,因为IE的前缀是msTransForm,第一个字母小写,而火狐等则是MozTransForm,第一个字母大写,所以如果是

-ms-开头的,先进行替换,然后在进行下面的转换。rdashAlpha是对 - 和后面的字母或数字进行匹配,然后调用facmelCase回调方法,进行转换为大写。

// Used by jQuery.camelCase as callback to replace()    fcamelCase = function( all, letter ) {        return letter.toUpperCase();    },

nodeName方法:

这个方法是判断节点名和传入的字符串是否相等,例如:

  console.log($.nodeName(document.documentElement, ‘html‘)); //true

源码:

nodeName: function( elem, name ) {        return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();    },

源码没什么特别的,只是需要将nodeName转换成小写,因为在不同浏览器中的nodeName可能大小写不一致。

JQuery源码解析-JQuery的工具方法(3)