人生就像一列開往墳墓的列車,路途上會有很多站,很難有人至始至終陪你走完全程,當陪你的人要下車時,即便不舍,也要心存感激,然后揮手告別。---sunnyhuang
對象和數組
本文將從幾個方面來探討對象和數組的特點。對于方法的判定盡量不要用掛在全局window
下面的方法。例如:isNaN()
, parseInt()
可以用Number.isNaN()
, Number.parseInt()
。
- 判定類型
- 對象和數組的遍歷
- 對象的一些常用方法
- 案例結合
1.判定類型
我們知道Javascript
有6中基本類型(ES6
的第七種symbol
),簡單的類型可以通過typeof
運算符來判定基本類型,判定引用類型和null
還是有一些小bug。
typeof
instanceof
Object.prototype.toString.call()
Number.isNaN()
本文主要講解判定數組和對象。
1. 判定數字
這是一個最簡單的辦法
typeof 5 // "number"
2. 判定數組
function isArray(arr) {
return Array.isArray ? Array.isArray(arr) : Object.prototype.toString.call(arr) === '[object Array]'
}
3. 判定對象
由于typeof null => object
, 所有我們需要排除null
function isObject(obj) {
return typeof obj === 'object' || typeof obj === 'function' && !!obj
}
4. 黑科技區分數組和對象
由于對象沒有length
,和數組卻有length
屬性 ,利用這一點可以很方便的區分對象和數組。
需求: 現在我們需要對于數組類型輸出索引和值相加,對于對象需要輸出key+value
let arr = [1,2,3] // sum(arr, console.log) => 1 3 5
let obj = {a: 'b', c: 'd'} //sum(obj, console.log) ab cd
function sum(obj, callback, cxt) {
let length = obj.length;
if(length === +length) {
arr.forEach((item,index) => {
callback.call(cxt||this, item+index)
})
}else {
Object.keys(obj).forEach(key => {
callback.call(cxt||this, key+obj[key])
})
}
}
5. Object.prototype.toString.call()
一般用這個方法判定類型。
對于面向對象編程,也有一切皆對象的說法,所有我們可以通過Object
的原型鏈上面的toString()
來判定類型。對于區分基本類型和引用類型很有效。
function getTypeof(obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
// 基本類型
getTypeof(1) === 'number' // true
getTypeof(null) === 'null' // true
getTypeof(undefined) === 'undefined' // true
getTypeof(false) === 'boolean'
// 引用類型
getTypeof([1]) === 'array' // true
getTypeof({}) === 'object' // true
getTypeof(function(){}) === 'function' // true
2.對象
- 對象定義屬性
Object.defineProperty()
- 獲取對象的屬性描述
Object.getOwnPropertyDescriptor(obj, props)
- 獲取對象的所有屬性(包括不可枚舉的屬性)
Object.getOwnPropertyNames(obj)
- 判定屬性是否是對象本身
obj.hasOwnProperty()
對象遍歷的三種方法對比
-
for ... in...
缺點 : 會遍歷原型鏈上面的屬性,一般配合hasOwnProperty()
-
Object.keys()
得到對象的keys數組,進行遍歷。 缺點:獲取不到不可枚舉的屬性 -
Object.getOwnPropertyNames()
可以遍歷對象的所有自身屬性(包括不可枚舉的)
let arr = {a: 'b'}
Object.prototype.test = 'test'
Object.defineProperty(arr, 'c', {
configurable: true,
enumerable: fasle, // 不可枚舉
writable: true,
value: 'bb'
})
// for in
for(let i in arr) {
console.log(i) // a test
}
// Object.keys()
Object.keys(arr).forEach(key => {console.log(key)})) // a
// Object.getOwnPropertyNames()
Object.getOwnPropertyNames(arr).forEach(console.log) // a c
3.案例結合
- 判定有name和age的用戶才是合法用戶
let condition = ['name', 'age']
// obj = {name : 'cccc', age: 50}
function valid(obj) {
return condition.every(key => {
return obj.hasOwnProperty(key)
})
}
上面這樣寫,可以很好的分離出條件和方法,很方便的給我們添加額外的條件。