javascript 中的object array
[TOC]
1. Object 数据类型
与python中的dict类型一样,object数据类型也是由减值以及数值组成的集合,属于一种无序序列对象的 所有键值均为字符串,所以加不加引号效果都一样,但是在进行引用时必须要加引号,如果键值是数值类型,也会转化为字符串。
键值的注意事项
如果键值不符合标识名的条件,(第一个字符为数值,包含空格或者运算符)则键值必须加上引号,否则会报错,所以建议所有键值都加引号
对象的每一个键名又被称为属性,其value可以是任何数据类型,通常把这个属性叫做方法,可以像函数一样进行调用,如果属性的值还是一个对象就可以形成链式引用
对象的每一个属性都可以进行动态指定,也可以进行动态更改,在进行引用时可以直接采用.
或者采用python dict的引用方式,但是注意对于键值标识名不合乎规定的需要采用后者引用方式
但是需要注意,如果使用方括号进行引用,必须加上引号,否则会被当做变量处理
表达式还是语句
由于对象采用大括号表示,就导致了一个问题,如果行首是一个大括号,到底是一个对象还是一个代码块。
JavaScript 引擎读到上面这行代码,会发现可能有两种含义。第一种可能是,这是一个表达式,表示一个包含foo
属性的对象;第二种可能是,这是一个语句,表示一个代码区块,里面有一个标签foo
,指向表达式123
。
为了避免这种歧义,V8 引擎规定,如果行首是大括号,一律解释为对象。不过,为了避免歧义,最好在大括号前加上圆括号。
这种差异在eval
语句(作用是对字符串求值)中反映得最明显。
上面代码中,如果没有圆括号,eval
将其理解为一个代码块;加上圆括号以后,就理解成一个对象。
对象的属性参数
通过对象的属性的参数可以设置对象属性的行为,基本参数如下:
[[value]]: 保存属性的值
[[Writable]]: 确定属性值是否可以被更改
[[get]]: 保存
getter
,当一个属性被read时会调用getter
函数[[set]]: 保存
setter
当一个属性被设置为一个值的时候,调用该函数,该函数需要传入value参数[[enumerable]]: 控制某个属性是否可以被迭代
[[configurable]]: 为假时该属性不可被删除,不可以改变属性的其他参数(除了value), 换言之,该参数控制属性元数据的读写铨叙
默认值如下:
Attribute Key
Default value
[[Value]]
undefined
[[Get]]
undefined
[[Set]]
undefined
[[Writable]]
false
[[Enumerable]]
false
[[Configurable]]
false
对象属性的操作
1. delete
delete
命令用于删除对象的属性,删除成功后会返回true
,使用该命令会删除指定的属性,这时再读取会得到undefined
,而且使用Object.keys()
函数进行属性的查看也找不到该属性。但删除一个不存在的属性时,不会报错,而是返回true
只有一种情况,delete命令会返回false,就是使用defineProperty
函数设定的属性不可更改
Object.defineProperty(obj, propName, proDesc)
:
该函数用于创建或者修改一个对象obj的属性proName,规定其描述符
根据该设定,将该对象的该属性设置为只读状态,不可以进行删除以及更改,进行delete时会返回false
2.属性存在
in
运算符用于判断属性是否存在,返回boolean类型,但是in
运算符不能判断某个属性时object本身的还是继承得到的,toString
属性是继承得到的,也会返回true
此时可以借助函数Object.hasOwnProperty()
判断是否为自身属性
3.属性的遍历
使用form...in
进行遍历操作,但是需要注意的是,只有enumerable
为真的属性才可以进行遍历,会跳过为假的属性;不仅遍历自身属性,而且遍历继承的属性,例如每个object都继承了toString
属性,但是不会被遍历到
4. with 语句
with
语句的格式如下:
它的作用是操作同一个对象的多个属性时,提供一些书写的方便。
注意,如果with
区块内部有变量的赋值操作,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量。
上面代码中,对象obj
并没有p1
属性,对p1
赋值等于创造了一个全局变量p1
。正确的写法应该是,先定义对象obj
的属性p1
,然后在with
区块内操作它。
这是因为with
区块没有改变作用域,它的内部依然是当前作用域。这造成了with
语句的一个很大的弊病,就是绑定对象不明确。
单纯从上面的代码块,根本无法判断x
到底是全局变量,还是对象obj
的一个属性。这非常不利于代码的除错和模块化,编译器也无法对这段代码进行优化,只能留到运行时判断,这就拖慢了运行速度。因此,建议不要使用with
语句,可以考虑用一个临时变量代替with
。
用作属性描述符的函数
Object.defineProperty(obj, propName, proDesc)
:Object.defineProperties(obj, propDescObj)
Object.create(proto, propDescObj?)
首先根据原型参数创建一个原型为
proto
的object,如果给出第二个参数,将此加入到属性参数列表中Object.getOwnPropertyDescriptor(obj, propName)
Returns the descriptor of the own (non-inherited) property of
obj whose name is propName. If there is no such property, undefined is returned.
2. eval 命令
eval()
接受一个字符串作为参数,并且将这个字符串参数当做语句运行,如果无法作为语句运行就会报错,同时放在该命令中的字符串应该有独自存在的意义,不可以与其他语句配合使用
注意eval函数没有自己的作用域,都在当前作用域执行,因此可能会修改当前已有变量值,造成安全问题,但是在使用严格模式时,其内部声明的作用域不会影响到外部.但是仍然可以更改外部变量的值
2. Array 数组
类似于python中的列表类型,数组可以存储任意数据类型 ,其类型是Object,是一种特殊类型的,只是每个属性的键值是数字而且是自增的 ,可以先定义后赋值,也可以在定义时赋值。可以使用Object.keys()
函数得到一个数组对象的键值,即为每个元素的下标
进行数组元素读取时可以采用对象的读取方式,但是不可以对数字型键值使用点操作符,只可以使用方括号结构
Array.length 属性
返回数组元素数量,js使用一个32位整数,保存数组的元素个数,所以最大的存储数量为(2^32^ - 1) 只要是数组就有length属性,该值是一个动态值,等于最后一个元素的键值+1
可以使用array.length = 0
将数组清空,将数组length属性人为设置为小于当前元素数量的值,将会自动删除后面多雨的元素,将其设置为不合法的值会报错。
in 运算符
in
运算符可以检查元素是否属于对象,也可以用来判断数组元素的存在情况,但是只能检查键值是否在数组中,可以用来检查某个位置是否为空位。注意length属性不过滤空位,使用delete语句删除数组元素时会将对应的位置设置为empty item
数组长度属性不会改变
读取已经删除的元素时,返回值为undefined
,对于数组中的空位,使用forEach
方法,for ... in
结构, Object.keys()
都会被过滤
数组的遍历
for... in
循环可以以遍历对象的方式遍历数组,也可以使用for循环,以及forEach()
方法
类似数组的对象
如果一个对象的所有键值都为正整数或者0,并且有length
属性,可以将该对象称为类似数组的对象。但是该对象中没有数组的push() pop()
等方法,而且length属性不是动态值,不会随着数组成员的变化而变化
常见的类似数组的对象包括函数的Arguments
对象,以及大多数的dom元素
可以使用Array.prototype.slice.call(arrayLike)
方法将类似数组的对象转化为数组;也可以通过call()
函数将数组的方法放到对象的上面
数组方法
添加删除元素:
arr.push(...items)
将元素加入到最后,并且返回数组长度arr.pop()
删除并返回最后一个元素arr.shift()
删除并返回第一个元素arr.unshift(...items)
将一个或者多个元素加入数组头部,返回数组长度arr.splice(index[, deleteCount, elm1, elm2, ..., elmN])
: 从下标index的元素开始,删除deleteCount个元素,并且将之后的参数加入到数组中,返回被删除的元素此函数可以作为数组操作中的一种瑞士军刀方法,可以满足数组增删改的所有需求
arr.slice(start, end)
复制index位于[start, end)之间的所有元素为新的数组
arr.concat(arg1, arg2)
连接两个数组或者数组和单个元素,返回一个新的数组,注意原数组无变化
数组元素查找
arr.indexOf(item, from)
:从f索引为from的位置开始向右查找,返回第一个找到的索引arr.lastIndexOf(item, from)
从右开始查找arr.includes(item, from)
是否包含该元素需要注意的是index方法使用的是绝对等运算符
===
,所以如果进行NaN的查找时,由于NaN != NaN所以会返回-1,可以使用includes方法
find and findIndex
对于一个对象的数组,使用某些条件对与对象进行查找,可以使用find方法.该方法需要传入一个函数作为参数,返回第一个使得函数返回值为真的元素
```javascript var array1 = [5, 12, 8, 130, 44];
function findFirstLargeNumber(element) { return element > 13; }
console.log(array1.findIndex(findFirstLargeNumber)); // expected output: 3
arr [ 'dsad', 44, 423, 'dsad', 'dsad', 'd', 'dsad' ] arr.find((item, index, array) => index == 4); 'dsad' arr.find((item, index) => index == 4); 'dsad' arr.find((item, index, array) => array[index] == 'd'); 'd' arr.find((item, index, array) => array.length == 7); 'dsad' // 恒为真则返回第一个值 ```
filter
filter
方法返回一个使得参数函数返回值为真的元素的数组```javascript let results = arr.filter(function (item, index, array) {
})
// [ 44, 423, 'dsad', 'dsad', 'd' ]
arr.filter(item => !isNaN(item)) [ 44, 423 ] arr.filter((item, index, array) => array.length == 5); [ 44, 423, 'dsad', 'dsad', 'd' ]
sort(fn)
将数组中所有元素作为字符串类型进行排序,注意数字也会转化为字符串类型,对于数字进行排序时需要传入函数进行操作.
由于数组对象可以包含任意类型的数据,为了便于进行统一的排序操作,将所有类型都看作字符串类型进行操作,其内部实现是一个优化后的快排算法.将会遍历数组每一个元素,使用给定的函数对于数据进行重排.实际上给定的函数只要在
a > b
时返回正值,反之返回负值即可reverse, split, join
数组的反向,分割以及拼接
```javascript let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) { alert(
A message to ${name}.
); // A message to Bilbo (and other names) } let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); // Bilbo, Gandalf
let str = 'vdsbs' undefined str.split('') [ 'v', 'd', 's', 'b', 's' ] ```
resuce/redueRight
生成方式,根据传入的函数生成相应的值,并且每一个item在调用该函数时可以使用上一个itme调用的返回值,可以实现递归的操作
参数与find map filter类似,但是多了一个初始值,用于作为第一次调用的值
Last updated