[導讀] underscore js原始碼Underscore js 沒有對原生 JavaScript 物件進行擴充,而是透過呼叫 _() 方法進行封裝,一旦封裝完成,原生 JavaScript 物件就會成為 Underscore 物件。判斷給定變數是否是物件 Is
#Underscore.js
沒有對原生JavaScript
物件進行擴充,而是透過呼叫_()
方法來封裝,一旦封裝完成,原生JavaScript
物件就會成為一個Underscore
物件。
// Is a given variable an object? _.isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' && !!obj; };
這是underscore.js
的判斷給定變數是否是object
的一段原始碼。 我們知道typeof
會傳回以下六個值:
1. 'undefined' --- 这个值未定义;2. 'boolean' --- 这个值是布尔值;3. 'string' --- 这个值是字符串;4. 'number' --- 这个值是数值;5. 'object' --- 这个值是对象或null;6. 'function' --- 这个值是函数。
而&&
的優先權要高與||
。 !!
的作用相當於Boolean()
,將其轉換為布林值。
// Is a 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);//3alert(t.nodeName);//#testalert(t.nodeValue);//测试
文字節點也算是節點,所以p的子節點是文字節點,所以回傳3
isArray = Array.isArray || function(object){ return object instanceof Array }
#Array.isArray()
方法:如果一個物件是數組就回傳true
,如果不是則回傳false
。
instanceof
用來判斷變數是否某個物件的實例,如
var a= []; alert(a instanceof Array);//返回 true
同時alert(a instanceof Object)
也會回傳true
isArray
傳回布林值,如果Array.isArray
為true
,則傳回true
,否則傳回object instanceof Array
的結果。
class2type = {},function type(obj) { return obj == null ? String(obj) : class2type[toString.call(obj)] || "object" } function isFunction(value) { return type(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
。 +length
可能你剛剛看到
slice.call(this)會覺得很納悶,其實不只
zepto.js的原始碼,包括
jQuery,
backbone
get: function(idx){ return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length] },
所以
slice.call(this)其實還是
Array.slce.call(this)
prototype.js原始碼
var push = array.push;var slice = array.slice;var splice = array.splice;因為
addClassName依賴
removeClassName(),所以先分析後者,
$()
//为对象添加 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; },
這句話的意思是如果元素物件不存在,則忽略不再繼續執行的意思,也就是終止的意思。 ##) 用作分隔符,那麼該物件中的每個字元之間都會被分割。方法
if(!element) return
!Array.prototype.push如果為
true,表示瀏覽器不支援該方法,則往下執行。 i] = arguments[i]
將傳遞進來的每個參數依序放入陣列中,最後傳回陣列的長度
存取物件可以使用
(.)表示法,也可以使用[]
來訪問,同樣訪問數組元素也是
源碼太多關聯了,所以不好單獨拿出來做分析,就舉一兩個簡單的例子:toArray方法
<pre class="hljs perl">split() 方法用于把一个字符串分割成字符串数组。</pre>
Array.prototype.slice.call(arguments)
能將具有
屬性的物件轉成數組,也就是說其目的是將arguments
物件的陣列提出來轉換為數組。例如:<pre class="hljs javascript">//是否拥有 class 属性值hasClassName: function(element, className) {
element = $(element); if (!element) return; var a = element.className.split(&#39; &#39;); for (var i = 0; i < a.length; i++) { if (a[i] == className) return true;//返回正确的处理结果
} return false;//返回错误的处理结果},</pre>
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)
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
对象字面量的写法
{键:值,键:值}
语法中的“健/值”
会成为对象的静态成员。如果给某个“健”指定的值是一个匿名函数,那么该函数就会变成对象的静态方法;否则就是对象的一个静态属性。
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
的实例。
以上是有關js框架的原始碼研究的詳細內容。更多資訊請關注PHP中文網其他相關文章!