jQuery源码学习笔记二
程序员文章站
2022-03-29 19:47:08
javascript // js源码在构造函数创建完就自动生成了 function Aaa(){}; Aaa.prototype.constructor = Aaa; var a = new Aaa(); alert(a.constructor); // function Aaa(){}; Aaa. ......
//添加实例属性和方法 jquery.fn = jquery.prototype = { // 版本,使用方式:$().jquery弹出当前引入的jquery的版本 jquery: core_version, // 修正指向问题(后有详解) constructor: jquery, // 初始化和参数管理 init: function( selector, context, rootjquery ) { var match, elem; // 写错之后的处理,如果写成: $(""), $(null), $(undefined), $(false),直接返回 if ( !selector ) { return this; } // 对字符串进行处理 if ( typeof selector === "string" ) { // 如果是这种$('<li>')或$('<li>1</li><li>2</li>') if ( selector.charat(0) === "<" && selector.charat( selector.length - 1 ) === ">" && selector.length >= 3 ) { // match = [ null, '<li>', null ];或者 match = [ null, '<li>1</li><li>2</li>', null ]; match = [ null, selector, null ]; //如果是$('#div1') $('.box') $('div') $('#div1 div.box') } else { //$('.box') $('div') $('#div1 div.box') match = null; //$('#div1') match = ['#div1',null,'div1']; //$('<li>hello') match = ['<li>hello','<li>',null]; match = rquickexpr.exec( selector ); //exec()后面详解 } // $('<li>') $('#div1') //$('#div1')的上下文为空,即context为false if ( match && (match[1] || !context) ) { if ( match[1] ) { // 如果是$('<li>',document)填写了第二个对象,并且第二个对象是原生,则直接返回该对象;$('<li>',$(document))如果返回的第二个对象是jquery,则将它转换成原生的对象 context = context instanceof jquery ? context[0] : context; // 1、jquery.parsehtml()函数用于将html字符串解析为对应的dom节点数组;使用一个html字符串创建一个数组的dom节点 jquery.merge( this, jquery.parsehtml( match[1], //需要解析并转成dom节点数组的html字符串 //指定在哪个document中创建元素,默认为当前文档的document,可能是iframe context && context.nodetype ? context.ownerdocument || context : document, //true,boolean类型指定传入的html字符串中是否包含脚本,默认为false true ) ); // 1、rsingletag.test( match[1] )匹配单标签,只能匹配<li>或<li></li>,其他都不行 // 2、jquery.isplainobject( context )函数用于判断指定参数是否是一个纯粹的对象。{ } 或new object()或{ name: "codeplayer"} if ( rsingletag.test( match[1] ) && jquery.isplainobject( context ) ) { for ( match in context ) { // jquery.isfunction用于判断参数是否是一个函数 if ( jquery.isfunction( this[ match ] ) ) { //如果是函数就直接调用该函数,示例:$('<li></li>',{title : 'hi',html : 'abcd',css : {background:'red'}}).appendto( 'ul' );其中html : 'abcd'就相当于this.html('abcd') this[ match ]( context[ match ] ); } else { //如果不是函数就直接添加属性 this.attr( match, context[ match ] ); } } } return this; // $('#div1')选择元素 } else { elem = document.getelementbyid( match[2] ); if ( elem && elem.parentnode ) { // inject the element directly into the jquery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } } else if ( !context || context.jquery ) { return ( context || rootjquery ).find( selector ); } else { return this.constructor( context ).find( selector ); } //对dom元素进行处理,$(this),$(document)。 //nodetype属性返回以数字值返回指定节点的节点类型。如果是元素节点,返回1;如果是属性节点,返回2 } else if ( selector.nodetype ) { this.context = this[0] = selector; this.length = 1; return this; // 对函数进行处理 } else if ( jquery.isfunction( selector ) ) { // 如果是函数$(function(){}),返回$(document).ready(function(){}); return rootjquery.ready( selector ); } // 对空对象或空数组进行处理 if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } // jquery.makearray()函数用于将一个类数组对象转换为真正的数组对象(详解) return jquery.makearray( selector, this ); }, // selector 存储选择字符串; selector: "", // length this对象的长度 length: 0, // toarray 专数组 toarray: function() { return core_slice.call( this ); }, // get 转原生合集 get: function( num ) { return num == null ? // return a 'clean' array this.toarray() : // return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // pushstack jq对象的入栈(先进后出) pushstack: function( elems ) { // build a new jquery matched element set var ret = jquery.merge( this.constructor(), elems ); // add the old object onto the stack (as a reference) ret.prevobject = this; ret.context = this.context; // return the newly-formed element set return ret; }, // each 遍历集合 each: function( callback, args ) { return jquery.each( this, callback, args ); }, // dom加载接口 ready: function( fn ) { jquery.ready.promise().done( fn ); return this; }, // 集合的截取 slice: function() { return this.pushstack( core_slice.apply( this, arguments ) ); }, // 集合的第一项 first: function() { return this.eq( 0 ); }, // 集合的最后一项 last: function() { return this.eq( -1 ); }, // 集合的指定项 eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushstack( j >= 0 && j < len ? [ this[j] ] : [] ); }, // 返回新集合 map: function( callback ) { return this.pushstack( jquery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, // 返回集合前一个状态 end: function() { return this.prevobject || this.constructor(null); }, // push、sort、splice内部使用 push: core_push, sort: [].sort, splice: [].splice };
部分详解
1、constructor: jquery
示例:
// js源码在构造函数创建完就自动生成了 function aaa(){}; aaa.prototype.constructor = aaa; var a = new aaa(); alert(a.constructor); // function aaa(){}; aaa.prototype.constructor = array; alert(a.constructor); // function array() { [native code] } aaa.prototype = { constructor : aaa, name : 'hello', age : 30 }; var a1 = new aaa(); alert(a1.constructor); // function aaa(){};
这个constructor属性非常容易被不小心修改掉,所以jquery需要修正指向
2、match = rquickexpr.exec( selector )
示例:
var rquickexpr = /^(?:\s*(<[\w\w]+>)[^>]*|#([\w-]*))$/; var selector = "#div1"; var match = rquickexpr.exec( selector ); console.log(match); //match = ['#div1',null,'div1'];
exec() 方法就是用来检索字符串中正则表达式的匹配,如果匹配到了那么就返回一个存放有结果的数组,如果没有匹配到就返回一个null;
match是数组,第0个元素是与正则表达式相匹配的文本,第1个元素是与正则表达式的第1个子表达式相匹配的文本(如果有的话),第2个元素是第2个子表达式相匹配的文本(如果有的话),第3个元素是第3个子表达式相匹配的文本(如果有的话),这里就是元素的id,不包含#。
3、jquery.makearray()
var adiv = document.getelementsbytagname('div');
adiv并不是一个真正的数组,可以用$.makearray(adiv)转成一个数组 ;$.makearray(adiv,{length:0})将它转成一个对象
$([]) $({})