上一章,讨论的是jQuery
对象及其原型上的extend()
方法,在源码中,实现了支持开发者自行扩展新方法的功能,但其实jQuery
也通过对extend()
传入一个对象参数来添加官方扩展方法,这些工具方法都是扩展在jQuery
类对象上的,所以调用时的写法要注意。
下面一起来看下扩展了哪些官方方法。
//总览:
jQuery.extend({
expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
isReady: true,
error: function(){},
noop: function(){},
isPlainObject: function(){},
isEmptyObject: function(){},
globalEval: function(){},
each: function(){},
trim: function(){},
makeArray: function(){},
inArray: function(){},
merge: function(){},
grep: function(){},
map: function(){},
guid: 1,
support: support
})
1、先来看下expando
属性,看它的实现,其实就是提供一个由jq版本号加上随机数字形成的唯一字符串。
error()
方法作用是抛出一个错误:
jQuery.extend({
error: function(msg){
throw new Error(msg)
}
})
2、isPlainObject()
方法作用是检测参数是否为纯对象,这个方法在上一章中也讲到过,所谓纯对象,就是正常键值对形式的对象。代码解释看注释:
jQuery.extedn({
isPlaniObject: function(obj){
var proto, Ctor;
// 如果参数不是对象 或者 通过call方式对参数调用toString()字符串化的结果不符合要求,则直接方法返回false,就不会再往下走了。
if( !obj || toString.call( obj ) != "[object Object]" ){
return false;
}
//返回参数对象的原型,在jQ工厂函数的头部,已经定义好getProto变量是Object.getPrototypeOf方法的引用
proto = getProto( obj );
//如果proto为假,其实就是指参数对象没有原型,由于前面已经对参数是对象进行判定,所以此时对象没有原型指对象属于类型 Object.create(null) 这样的情况,自然参数也是属于 纯对象
if(!proto){
return true;
}
// 对象如果是被全局对象函数构造出来的,则返回其构造函数本身
// 这里hasOwn变量是 {}.hasOwnProperty() 方法的引用
// hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否有指定的值
Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; //这里其实就是考的js中的构造函数。
return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; //构造函数及其实例 返回false
}
})
只有键值对形式的js对象,才返回true,才被视为纯对象,即使是构造函数和普通函数等“对象”也不行。
3、isEmptyObject()
方法,看命名即知其作用是检测一个对象是否为空对象,即不包含任何可枚举属性。
jQuery.extend({
isEmptyObject: function(obj){
var name;
if(name in obj){
return false;
}
return true;
}
})
通过for...in...
来检测对象是否有可枚举属性来,判断是否为空对象。
这里复习下for...in...
作用,其是用来遍历对象的可枚举属性的,包括对象原型上的可枚举属性。而如果只想要遍历对象本身的属性且不想遍历出对象原型上的属性,则需要使用hasOwnProperty()
方法:
var obj = {
a: 1,
b: 2,
c: 3
}
function A(x) {
this.x = x
}
A.prototype = obj; //将构造函数A的原型指向对象obj
var a = new A(10);
console.log('所有可枚举属性,包含原型上的属性:');
for(var i in a){
console.log(i);
}
console.log('自有可枚举属性:');
for(var i in a){
if(a.hasOwnProperty(i)){
console.log(i);
}
}
//打印结果:
/*
所有可枚举属性,包含原型上的属性:
x
a
b
c
自有可枚举属性:
x
*/
4、globalEval()
,用于全局性的执行一段代码,其执行代码的作用域是全局作用域,这个方法还是尽量少用,毕竟作用域的使用还是规范的好。
5、each()
方法,这个方法大家就非常熟悉了,遍历对象或数组用的,来看看该方法的内部实现:
jQuery.extend({
each:function(obj, callback){
var length, i=0;
if(isArrayLike( obj )){ //如果是类数组
length = obj.length;
for( ; i<length; i++ ){
if( callback.call( obj[i], i, obj[i] ) === false ){
break;
}
}
}else { //如果是纯对象
for( i in obj ){
if( callback.call( obj[i], i, obj[i] ) === false ){
break;
}
}
}
return obj;
}
})
看上述代码实现可知,方法内部对参数obj
进行了对象和类数组的判别,同时在遍历时,对传入的回调函数也进行了控制:callback.call( obj[i], i, obj[i] ) === false
,通过call
方法来将回调函数中的this
对象指向当前循环到的属性值上,传入回调函数中的参数标识出属性名和属性值的先后顺序,并且还添加false
来为回调函数增加了手动停止遍历循环的功能。
// 接上上例的构造函数A的实例对象a来做演示
console.log(jQuery.each( a, function(index, val){
if(index === 'a'){ //当遍历到的属性为a时,返回false来跳出遍历循环
return false;
}else {
console.log(index + ": " + val);
}
} ));
时间关系,今天就写这么多吧,更多关于jQuery.extend()
扩展出来的工具方法,请看下篇。