首页 > 代码库 > 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)