jQuery源码的基础知识
序言:DOM addEventListener
attachEvent与addEventListener区别
适应的浏览器版本不同,同时在使用的过程中要注意
attachEvent方法 按钮onclick
addEventListener方法 按钮click
一、arguments对象:
1、arguments 属性
为当前执行的function对象返回一个arguments对象。
2、function.arguments
function参数是当前执行函数的名称,可以省略。
3、arguments.length
arguments 对象的 length 属性包含了传递给函数的参数的数目。arguments 对象所包含的单个参数,访问方法与数组中所包含的参数的访问方法相同。
4、arguments当作数组使用
arguments虽然不是数组,但可以当作数组使用,下标由 0 开始,所以:
arguments[0] 表示接收的第一个参数
arguments[1] 表示接收的第二个参数
……
for (var i = 1; i < arguments.length; i++)
var s = arguments[i];
5、arguments转换数组
var args = Array.prototype.slice.call(arguments);
二、call方法:
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
三、apply方法:
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
四、call方法和apply方法的区别
call和apply方法通常被用来实现类似继承一样的功能,以达到代码复用的功效。它们的区别主要体现在参数上。
Apply:
var v = new fn( " str " );
// 上一句相当于下面的代码
var v = {};
fn.apply(v, [ "str" ]);
五、prototype原型
1、当我们使用javascript定义一个类的时候,系统会自动生成一个对应的原型,而使用类的prototype可以指向这个原型。
2、定义类的时候,一般使用函数定义,而那个函数就是构造函数,构造函数可以使用constructor来指定。
3、当构造函数和prototype定义了相同的属性或者方法的时候,构造函数的优先级要更高。
4、原型中,不能调用构造函数的私有变量,和通过传参传进来的值。
5、prototype中定义的变量和属性都是公有的。
6、任何一个类,当有多次实例化的时候,在内存中只有一个原型,而构造函数在内存中会有多个副本。
7、在构造函数中可以调用prototype中的属性和方法。
实例:
function fn(){}; fn.prototype={ pro:'原型' } var o=new fn(); alert(o.pro);
六、匿名函数自动执行(function(){……}())
1. 什么是自执行的匿名函数?
它是指形如这样的函数: (function {// code})();
2. 疑问
为什么(function {// code})();可以被执行, 而function {// code}();却会报错?
3. 分析
(1). 首先, 要清楚两者的区别:
(function {// code})是表达式, function {// code}是函数声明.
(2). 其次, js"预编译"的特点:
js在"预编译"阶段, 会解释函数声明, 但却会忽略表式.
(3). 当js执行到function() {//code}();时, 由于function() {//code}在"预编译"阶段已经被解释过, js会跳过function(){//code}, 试图去执行();, 故会报错;
当js执行到(function {// code})();时, 由于(function {// code})是表达式, js会去对它求解得到返回值, 由于返回值是一 个函数, 故而遇到();时, 便会被执行.
另外, 函数转换为表达式的方法并不一定要靠分组操作符(),我们还可以用void操作符,~操作符,!操作符……
如:
!function(){ alert("另类的匿名函数自执行"); }();
七、自定义的extend静态方法
方法一:
var fn=function(){}; fn.extend = function(o, p) { if ( !p ) { p = o; o = this; } for ( var i in p ) o[ i ] = p[ i ]; alert(o[ i ]); alert(o); return o; } fn.extend({ method:function(){ alert("静态方法"); } }); fn.method(); //静态方法
方法二:
var fn=function(){}; fn.extend = function() { var options, target = arguments[0] || {}; if ( !options ) { options = target; target = this; } for ( var i in options ) target[ i ] = options[ i ];//执行对象直接量,把options[ i ]装载到target[ i ],最后返回target新对象。 return target; } fn.extend({ method:function(){ alert("静态方法"); } }); fn.method();
源码解析如下:
var options={ a:function(){ alert("a"); }, b:function(){ alert("b"); } } var target={}; for ( var i in options ) target[i]=options[i];//复制对象,重新装载 target.a(); //a
|
![]() |
方法三:
var fn=function(){}; Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; } Object.prototype.extend = function(object) { return Object.extend.apply(this, [this, object]); } fn.extend({ method:function(){ alert("静态方法"); } }); fn.method();