摘要:對象字面量形式通過構造函數創建中是如何判斷的呢判斷是否為純粹的對象,必須滿足首先必須是對象不是對象并且原型要和的原型相等方法返回指定對象的原型即內部屬性的值如果沒有繼承屬性,則返回。
前言
時間過得可真快,轉眼間2017年已去大半有余,你就說嚇不嚇人,這一年你成長了多少,是否荒度了很多時光,亦或者天天向上,收獲滿滿。今天主要寫一些看Zepto基礎模塊時,比較實用的部分內部方法,在我們日常工作或者學習中也會用的到。
源碼倉庫
原文鏈接
面試或者工作中經常遇到要將多維數組鋪平成一維數組。例如將[1, 2, [3], [4], [5]]最后變成[1, 2, 3, 4, 5]
function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
這里先將$.fn.concat理解成原生數組的concat方法,我們會發現,其實他只能鋪平一層。例如
[1, 2, [3], [4, [5]]] => [1, 2, 3, 4, [5]]
那怎樣才能將多層嵌套的數組完全鋪平為一層呢?這里介紹兩種方式。
方式1
let flatten = (array) => { return array.reduce((result, val) => { return result.concat(Array.isArray(val) ? flatten(val) : val) }, []) }
測試
let testArr1 = [1, 2, 3, 4] let testArr2 = [1, [2], 3, [4, [5, [6, [7]]]]] console.log(flatten(testArr1)) // => [1, 2, 3, 4] console.log(flatten(testArr2)) // => [1, 2, 3, 4, 5, 6, 7]
方式2
let flatten = (array) => { let result = [] let idx = 0 array.forEach((val, i) => { if (Array.isArray(val)) { let value = flatten(val) let len = value.length let j = 0 result.length += len while ( j < len) { result[idx++] = value[j++] } } else { result[idx++] = val } }) return result }
同樣和上面得到的結果一致
2. 數組去重(uniq)數組去重可謂是老生常談的話題了,方式有非常多。好久之前寫過一篇關于去重的文章,歡迎查看。
let uniq = function (array) { return filter.call(array, function (item, idx) { return array.indexOf(item) == idx }) }
結合數組的filter方法,查看數組的某項出現的索引是不是與idx相等,不相等,肯定出現過2次以上,即將其過濾掉。其實結合es6中的Set數據結構,可以很方便的做到數組去重。
let uniq = (array) => { return [...new Set(array)] }
測試
let testArr = [1, 1, 2, 3, 0, -1, -1] console.log(uniq(testArr)) // => [1, 2, 3, 0, -1]3. 連字符轉駝峰(camelize)
這個方法挺實用的,可以將a-b-c這種形式轉換成aBC,當然下劃線的數量可以是多個,a---b-----c => aBC
let camelize = function (str) { return str.replace(/-+(.)?/g, function (match, chr) { return chr ? chr.toUpperCase() : "" }) }4. 判斷是否為document對象(isDocument)。
通過dom元素的nodeType屬性可以知道其屬于哪種元素類型。結合下面這張表(developer.mozilla.org/en-US/docs/Web/API/Node/nodeType),其實不僅僅可以寫出判斷是否為document對象,還可以判斷是否為元素對象等。
function isDocument (obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }5. 判斷obj是否為類數組(likeArray)
什么是類數組對象呢?
類數組對象:
含有指向對象元素的數字索引下標以及length屬性標志屬性的個數
不含有數組的push、concat等方法
常見的類數組對象有auguments,document.getElementsByClassName等api獲取的dom集合,符合上述條件的對象等。
function likeArray(obj) { // !!obj 直接過濾掉了false,null,undefined,""等值 // 然后obj必須包含length屬性 var length = !!obj && "length" in obj && obj.length, // 獲取obj的數據類型 type = $.type(obj) // 不能是function類型,不能是window // 如果是array則直接返回true // 或者當length的數據類型是number,并且其取值范圍是0到(length - 1)這里是通過判斷length - 1 是否為obj的屬性 return "function" != type && !isWindow(obj) && ( "array" == type || length === 0 || (typeof length == "number" && length > 0 && (length - 1) in obj) ) }
代碼上了注釋,主要我們來對比一下underscore中是如何判斷是否為類數組的。
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var getLength = property("length"); var isArrayLike = function(collection) { var length = getLength(collection); return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; };
underscore中判斷類數組比較寬松一些,MAX_ARRAY_INDEX是JavaScript 中能精確表示的最大數字,主要判斷對象的length屬性是否為數字類型,并且是否大于0且在MAX_ARRAY_INDEX范圍內。
zepto中類數組判斷就比較嚴格了,因為window和函數其實都有length屬性,這里把他們給過濾掉了。
6. 判斷是否為window對象window對象的window屬性指向其本身,我們來直接看下mdn上的解釋。
function isWindow (obj) { return obj != null && obj == obj.window }
但實際上下面的代碼也會被認為是window對象。
let a = {} a.window = a a === a.window // true isWindow(a) // true7. 判斷數據類型
利用Object.prototype.toString方法來做數據類型的判斷。
let class2type = {} let toString = class2type.toString // Populate the class2type map $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type["[object " + name + "]"] = name.toLowerCase() })
最后class2type會變成
class2type = { "[object Boolean]": "boolean", "[object Array]": "array", "[object Number]": "number" ... }
接著就是type函數的定義了
function type(obj) { return obj == null ? String(obj) : class2type[toString.call(obj)] || "object" }
首先如果傳入的obj是null或者undefined,則用String函數返貨null或者undefined,而toString.call(obj)返回的正是形如[object Array],所以再結合上面的class2type變量,正好就可以得到例如。
type([]) => array type(1) => number8. 判斷是夠為純粹的對象(isPlainObject)
有時候我們想要符合這樣條件的對象。但是js中沒有直接給到能夠判斷是否為純粹的對象的方法。
// 對象字面量形式 let obj = { name: "qianlongo" } // 通過Object構造函數創建 let person = new Object({ name: "qianlongo", sex: "boy" })
zepto中是如何判斷的呢?
// 判斷obj是否為純粹的對象,必須滿足 // 首先必須是對象 --- isObject(obj) // 不是window對象 --- !isWindow(obj) // 并且原型要和 Object 的原型相等 function isPlainObject(obj) { return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype }
Object.getPrototypeOf() 方法返回指定對象的原型(即, 內部[[Prototype]]屬性的值),如果沒有繼承屬性,則返回 null 。
9. 判斷是否為空對象(isEmptyObject)// 判斷是否為空對象 // 使用for in遍歷,只要obj有屬性則認為不是空對象 $.isEmptyObject = function (obj) { var name for (name in obj) return false return true }
主要是通過走一遍for循環,來確定,所以會將以下數據也認為是空對象。
null
undefined
[]
""
1024(數字)
true or false
{}
new Person() // 自定義的構造函數
所以這里判斷空對象的初衷到底是不是只為了判斷形如{},new Object()呢
結尾暫時就更新這些,后續在閱讀源碼的過程中會陸續補充
參考資料
讀Zepto源碼之內部方法
jQuery.isPlainObject
對jQuery.isPlainObject()的理解
Object.getPrototypeOf()
文章記錄
原來你是這樣的jsonp(原理與具體實現細節)
誰說你只是"會用"jQuery?
向zepto.js學習如何手動觸發DOM事件
mouseenter與mouseover為何這般糾纏不清?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84939.html
摘要:對象字面量形式通過構造函數創建中是如何判斷的呢判斷是否為純粹的對象,必須滿足首先必須是對象不是對象并且原型要和的原型相等方法返回指定對象的原型即內部屬性的值如果沒有繼承屬性,則返回。 前言 時間過得可真快,轉眼間2017年已去大半有余,你就說嚇不嚇人,這一年你成長了多少,是否荒度了很多時光,亦或者天天向上,收獲滿滿。今天主要寫一些看Zepto基礎模塊時,比較實用的部分內部方法,在我們日...
摘要:對象字面量形式通過構造函數創建中是如何判斷的呢判斷是否為純粹的對象,必須滿足首先必須是對象不是對象并且原型要和的原型相等方法返回指定對象的原型即內部屬性的值如果沒有繼承屬性,則返回。 前言 時間過得可真快,轉眼間2017年已去大半有余,你就說嚇不嚇人,這一年你成長了多少,是否荒度了很多時光,亦或者天天向上,收獲滿滿。今天主要寫一些看Zepto基礎模塊時,比較實用的部分內部方法,在我們日...
摘要:舉例需要注意的是,此時回調函數中的指向的就是數組或者對象的某一項。中提供的拷貝方法,默認為淺拷貝,如果第一個參數為布爾值則表示深拷貝。 前言 平時開發過程中經常會用類似each、map、forEach之類的方法,Zepto本身也把這些方法掛載到$函數身上,作為靜態方法存在,既可以給Zepto的實例使用,也能給普通的js對象使用。今天我們主要針對其提供的這些api做一些源碼實現分析。 源...
摘要:舉例需要注意的是,此時回調函數中的指向的就是數組或者對象的某一項。中提供的拷貝方法,默認為淺拷貝,如果第一個參數為布爾值則表示深拷貝。 前言 平時開發過程中經常會用類似each、map、forEach之類的方法,Zepto本身也把這些方法掛載到$函數身上,作為靜態方法存在,既可以給Zepto的實例使用,也能給普通的js對象使用。今天我們主要針對其提供的這些api做一些源碼實現分析。 源...
閱讀 3274·2023-04-25 18:03
閱讀 1143·2021-11-15 11:38
閱讀 5522·2021-10-25 09:45
閱讀 840·2021-09-24 09:48
閱讀 2272·2021-09-22 15:34
閱讀 1734·2019-08-30 15:44
閱讀 2675·2019-08-30 13:12
閱讀 604·2019-08-29 16:05