underscorejs源码Underscorejs 没有对原生 JavaScript 对象进行扩展,而是通过调用 _() 方法进行封装,一旦封装完成,原生 JavaScript 对象便成为一个 Underscore 对象。判断给定变量是否是对象 Is
underscore.js源码
Underscore.js没有对原生JavaScript 对象进行扩展,而是通过调用 _() 方法进行封装,一旦封装完成,原生 JavaScript 对象便成为一个 Underscore 对象。
判断给定变量是否是对象
// Isa given variable an object?
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type ==='object' && !!http://www.sm136.com
};
这是underscore.js的判断给定变量是否是object的一段源码。 我们知道typeof会返回如下六个值:
1.'undefined' --- 这个值未定义;
2.'boolean' --- 这个值是布尔值;
3.'string' --- 这个值是字符串;
4.'number' --- 这个值是数值;
5.'object' --- 这个值是对象或null;
6.'function' --- 这个值是函数。
而&&的优先级要高与||。!!的作用相当于Boolean(),将其转换为布尔值。
判断给定值是否是DOM元素
// Isa given value a DOM element?
_.isElement = function(obj) {
return !!(obj && obj.nodeType=== 1);
};
同样!!相当于Boolean()的作用,nodeType=== 1则说明是元素节点,属性attr是2 ,文本text是3
<body>
<p id="test">测试</p>
<script>
var t = document.getElementById('test');
alert(t.nodeType);//1
alert(t.nodeName);//p
alert(t.nodeValue);//null
</script>
</body>
firstChild属性
var t= document.getElementById('test').firstChild;
alert(t.nodeType);//3
alert(t.nodeName);//#test
alert(t.nodeValue);//测试
文本节点也算是一个节点,所以p的子节点是文本节点,所以返回3
zepto源码
判断是否是数组
isArray= Array.isArray ||
function(object){ return objectinstanceof Array }
Array.isArray()方法:如果一个对象是数组就返回true,如果不是则返回false。
instanceof用于判断一个变量是否某个对象的实例,如
var a=[];
alert(ainstanceof Array);//返回 true
同时 alert(a instanceof Object) 也会返回 true
isArray返回布尔值,如果Array.isArray为true,则返回true,否则返回objectinstanceof Array的结果。
数据类型判断
class2type= {},
functiontype(obj) {
return obj == null ? String(obj) :
class2type[toString.call(obj)] ||"object"
}
function isFunction(value) { returntype(value) == "function" }
function isWindow(obj) { return obj != null && obj ==obj.window }
function isDocument(obj) { return obj != null && obj.nodeType== obj.DOCUMENT_NODE }
function isObject(obj) { return type(obj) == "object" }
class2type是一个空对象,实际上一个什么都没有的空对象是这样创建的Object.create(null);
我们可以通过Object.prototype.toString.call()方法来判断数据类型,例如:
console.log(Object.prototype.toString.call(123))//[object Number]
console.log(Object.prototype.toString.call('123'))//[object String]
console.log(Object.prototype.toString.call(undefined))//[object Undefined]
console.log(Object.prototype.toString.call(true))//[object Boolean]
console.log(Object.prototype.toString.call({}))//[object Object]
console.log(Object.prototype.toString.call([]))//[object Array]
console.log(Object.prototype.toString.call(function(){}))//[object Function]
首先如果参数obj是undefined或null,则通过String(obj)转换为对应的原始字符串“undefined”或“null”。
然后class2type[toString.call(obj)]首先借用Object的原型方法toString()来获取obj的字符串表示,返回值的形式是 [object class],其中的class是内部对象类。
然后从对象class2type中取出[object class]对应的小写字符串并返回;如果未取到则一律返回“object。
get方法
get:function(idx){
return idx === undefined ?slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
},
取集合中对应指定索引的值,如果idx小于0,则idx等于idx+length,length为集合的长度.
可能你刚看到slice.call(this)会觉得很纳闷,其实不仅是zepto.js的源码,包括jQuery,backbone的源码都是这么写的,只不过它们在最开头做了声明:
varpush = array.push;
varslice = array.slice;
varsplice = array.splice;
所以slice.call(this)其实还是Array.slce.call(this)
prototype.js源码
//为对象添加 class 属性值
addClassName: function(element, className) {
element = $(element);
Element.removeClassName(element,className);
element.className += ' ' + className;
},
//为对象移除 class 属性值
removeClassName: function(element,className) {
element = $(element);
if (!element)
return;
var newClassName = '';
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
if (a[i] != className) {
if (i > 0)
newClassName += ' ';
newClassName += a[i];
}
}
element.className = newClassName;
},
因为addClassName依赖于removeClassName(),所以先分析后者,$()是先将元素封装成prototype对象,
if(!element) return
这句的意思就是如果元素对象不存在,则忽略不再继续执行的意思,也就是终止的意思。
split()方法用于把一个字符串分割成字符串数组。
如果把空字符串 ("") 用作 分隔符,那么 该对象 中的每个字符之间都会被分割。
判断是否拥有 class 属性值
//是否拥有 class 属性值
hasClassName:function(element, className) {
element = $(element);
if (!element)
return;
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
if (a[i] == className)
return true;//返回正确的处理结果
}
return false;//返回错误的处理结果
},
兼容旧版本浏览器增加Array的push方法
/**
* 为兼容旧版本的浏览器增加 Array 的 push方法。
*/
if(!Array.prototype.push) {
Array.prototype.push = function() {
var startLength = this.length;//this指代Array
for (var i = 0; i <arguments.length; i++)
this[startLength + i] =arguments[i];//this依旧指代Array
return this.length;
}
}
!Array.prototype.push如果为true,说明浏览器不支持该方法,则往下执行。this[startLength + i] = arguments[i]将传递进来的每个参数依次放入数组中,最后返回数组的长度
访问对象可以使用(.)表示法,也可以使用[]来访问,同样访问数组元素也是
jQuery源码
jQuery源码太多关联了,所以不好单独拿出来做分析,就举一两个简单的例子吧:
toArray方法
jQuery.prototype= {
toArray: function() {
return slice.call( this );
},
}
Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,也就是说其目的是将arguments对象的数组提出来转化为数组。例如:
<script>
var a= {length:4,0:'zero',1:'one',2:'two'};
console.log(Array.prototype.slice.call(a));// Array [ "zero","one", "two", <1 个空的存储位置> ]
</script>
Array
这是我们想要的基对象名称
prototype
这可以被认为是一个数组的实例方法的命名空间
slice
这提取数组的一部分并返回新的数组,并没有开始和结束索引,它只是返回一个数组的拷贝
call
这是一个非常有用的功能,它允许你从一个对象调用一个函数并且使用它在另一个上下文环境
下面的写法是等效的:
Array.prototype.slice.call== [].slice.call
看这个例子:
object1= {
name:'frank',
greet:function(){
alert('hello '+this.name)
}
};
object2= {
name:'trigkit4'
};
//object2没有greet方法
// 但我们可以从object1中借来
object1.greet.call(object2);//弹出hello trigkit4
分解一下就是object1.greet运行弹出hello + 'this.name',然后object2对象冒充,this就指代object2
var t= function(){
console.log(this);// String ["t", "r", "i", "g", "k","i", "t", "4" ]
console.log(typeof this); // Object
console.log(this instanceof String); // true
};
t.call('trigkit4');
call(this)指向了所传进去的对象。
在Object.prototype中已经包含了一些方法:
1.toString ( )
2.toLocaleString ( )
3.valueOf ( )
4.hasOwnProperty (V)
5.isPrototypeOf (V)
6.propertyIsEnumerable (V)
on方法
jQuery.fn.extend({
on: function( types, selector, data, fn,/*INTERNAL*/ one ) {
var type, origFn;
// Types can be a map of types/handlers
if ( typeof types ==="object" ) {
// ( types-Object, selector, data )
if ( typeof selector !=="string" ) {
// ( types-Object, data )
data = data || selector;
selector = undefined;
}
}
})
jQuery.extend(object):为扩展jQuery类本身.为类添加新的方法。
jQuery.fn.extend(object):给jQuery对象添加方法。
!= 在表达式两边的数据类型不一致时,会隐式转换为相同数据类型,然后对值进行比较.
!== 不会进行类型转换,在比较时除了对值进行比较以外,还比较两边的数据类型, 它是恒等运算符===的非形式。
on :function(){} 是js对象字面量的写法
{键:值,键:值}语法中的“健/值”会成为对象的静态成员。如果给某个“健”指定的值是一个匿名函数,那么该函数就会变成对象的静态方法;否则就是对象的一个静态属性。
图片描述
jQuery类型判断
type:function( obj ) {
if ( obj == null ) {
return obj + "";
}
return typeof obj ==="object" || typeof obj === "function" ?
class2type[ toString.call(obj) ] ||"object" :
typeof obj;
},
前面已经分析了,class2type = {};所以class2type[toString.call(obj) ] =
{}.toString.call(obj)。它的作用是改变toString的this指向为object的实例。
联系客服