视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
深度解析jquery中的核心功能
2020-11-27 20:19:39 责编:小采
文档

核心功能包括:

jquery是如何定义的,如何调用的,如何扩展的。掌握核心方法是如何实现的,是理解jQuery源码的关键。这里理解了一切豁然开朗。

1,如何定义,即入口

// Define a local copy of jQuery

var jQuery = function( selector, context ) {

// The jQuery object is actually just the init constructor ‘enhanced’

return new jQuery.fn.init( selector, context, rootjQuery );//jQuery对象仅仅是构造函数jQuery.prototype.init加强版

}

2,jQuery的原型,及与jQuery.fn.init的关系

//定义对象方法,也即只有通过$(“xx”).的方式才能调用。

jQuery.fn = jQuery.prototype = {

init:function( selector, context, rootjQuery ) {

return jQuery.makeArray( selector, this );

}

其他还有很多属性和方法,

属性有:jquery,constructor, selector, length

方法有:toArray,get, pushStack,each, ready,slice, first,last,eq, map,end, push, sort, splice

}

//把jQuery.prototype赋给jQuery.prototype.init.prototype,是为了后面的实例化

// Give the init function the jQuery prototype for later instantiation

jQuery.fn.init.prototype = jQuery.fn;

也即是,$(“xx”)拥有了实例方法,可以调用。(调用jQuery.prototype下定义的方法)

为什么jQuery要返回jQuery.fn.init对象?

jQuery = function( selector, context ) {

// The jQuery object is actually just the init constructor ‘enhanced’

return new jQuery.fn.init( selector, context, rootjQuery );

}

jQuery.fn = jQuery.prototype = {

……

}

jQuery.fn.init.prototype = jQuery.fn;

在 stackoverflow 上找到类似问题:

http://stackoverflow.com/questions/47560/help-understanding-jquerys-jquery-fn-init-why-is-init-in-fn

还有这个

http://stackoverflow.com/questions/18560/why-does-jquery-use-new-jquery-fn-init-for-creating-jquery-object-but-i-can/1858537#1858537

I believe the code is written in this fashion so that the new keyword is not required each time you instantiate a new jQuery object and also to delegate the logic behind the object construction to the prototype. The former I believe is to make the library cleaner to use and the latter to keep the initialisation logic cleanly in one place and allow init to be recursively called to construct and return an object that correctly matches the passed arguments.

3,extend扩展对象方法和静态方法原理

jQuery.extend = jQuery.fn.extend = function() {

var target = arguments[0] || {};

return target;

}

使用extend就方便了,无非就是$.extend({});和$.fn.extend({});如果你能在看到fn时理解联想到是jQuery.prototype就好了。

再通过this作用域看一下:

$.extend ->this是$-> this.aa()

$.fn.extend->this是$.fn-> this.aa()

附extend实现细节:

使用场景:

1,扩展一些函数

只有一个参数。例如:$.extend({f1:function(){},f2:function(){},f3:function(){}})

2,合并多个对象到第一个对象

(1)浅copy,第一个参数是目标对象。例如

var a = {name:”hello”}

var b = {age:30}

$.extend(a,b);//a={name:”hello”,age:30}

(2)深copy,第一个参数是TRUE,第二个参数是目标对象。例如

var a = {name:{job:”it”}};

var b = {name:{age: 30 }};

//$.extend(a,b);

$.extend(true,a,b);

console.log(a);

jQuery.extend = jQuery.fn.extend = function() {
 var options, name, src, copy, copyIsArray, clone,
 target = arguments[0] || {},
 i = 1,
 length = arguments.length,
 deep = false;

 // 是不是深复制 Handle a deep copy situation
 if ( typeof target === "boolean" ) {
 deep = target;
 target = arguments[1] || {};
 // skip the boolean and the target
 i = 2;
 }

 // 不是对象类型 Handle case when target is a string or something (possible in deep copy)
 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 target = {};
 }

 // 扩展插件的情况 extend jQuery itself if only one argument is passed
 if ( length === i ) {//$.extend({f1:function(){},f2:function(){},f3:function(){}})
 target = this;//this是$,或是$.fn
 --i;
 }

 for ( ; i < length; i++ ) {//可能有多个对象扩展到第一个对象上
 // Only deal with non-null/undefined values
 if ( (options = arguments[ i ]) != null ) {//options是一个对象
 // Extend the base object
 for ( name in options ) {
 src = target[ name ]; //src是target里已经存在的value(也可能不存在)
 copy = options[ name ];//copy是待合入的一个value

 // 防止循环引用 Prevent never-ending loop
 if ( target === copy ) {//例如:var a={};$.extend(a,{name:a});//可能导致循环引用
 continue;
 }

 // if是深复制else是浅复制 Recurse if we're merging plain objects or arrays
 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 : {};
 }

 // 亮了,直至剥离至最深一层非对象类型,而且是逐个。Never move original objects, clone them
 target[ name ] = jQuery.extend( deep, clone, copy );

 // Don't bring in undefined values
 } else if ( copy !== undefined ) {
 target[ name ] = copy;//target[ name ] = options[ name ];
 }
 }
 }
 }

 // Return the modified object
 return target;
};

jQuery.extend({…})分析

看一下是如何写的

jQuery.extend({

prop:””

method:function(){}

});

可以看出,这些方法是jQuery的静态属性和方法(也即是工具方法),将来既可以直接提供给用户使用,也可以在内部使用。

具体实现的工具属性和方法有(同时也标注了哪些在内部使用)

jQuery.extend({

expando : 生成唯一JQ字符串(内部)

noConflict() : 防止冲突

isReady : DOM是否加载完(内部)

readyWait : 等待多少文件的计数器(内部)

holdReady() : 推迟DOM触发

ready() : 准备DOM触发

isFunction() : 是否为函数

isArray() : 是否为数组

isWindow() : 是否为window

isNumeric() : 是否为数字

type() : 判断数据类型

isPlainObject() : 是否为对象自变量

isEmptyObject() : 是否为空的对象

error() : 抛出异常

parseHTML() : 解析节点

parseJSON() : 解析JSON

parseXML() : 解析XML

noop() : 空函数

globalEval() : 全局解析JS

camelCase() : 转驼峰

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

each() : 遍历集合

trim() : 去前后空格

makeArray() : 类数组转真数组

inArray() : 数组版indexOf

merge() : 合并数组

grep() : 过滤新数组

map() : 映射新数组

guid : 唯一标识符(内部)

proxy() : 改this指向

access() : 多功能值操作(内部)

now() : 当前时间

swap() : CSS交换(内部)

});

jQuery.ready.promise = function(){}; 监测DOM的异步操作(内部)

function isArraylike(){} 类似数组的判断(内部)

下载本文
显示全文
专题