JS的数据类型
- 数字(Number)
- 字符串(String)
- 布尔(Boolean)
- 符号(Symbol)
- 空(Undefined)
- 空(Null)
- 对象(Object)
关于JS的数据类型,可以简写为:“四基两空一对象”。其中,前六种数据类型为简单的数据类型,Object为唯一的复杂类型。 - 五个fasly值:undefined、null、NaN、0、''
JS对象
- 定义
JS对象是无序的数据集合,也是键值对的集合。(键值对中的键(key)是指对象的属性名,值(value)指的是对象的属性值) - 对象的声明
简写,一般都用这种写法
let obj = { 'name' : 'frank' , 'age' : 18}
下面这种是正规写法但是一般不用。
let obj = new Object ({ 'name' : 'frank' , 'age' : 18})
- 键名是字符串,不是标识符,可以包含任意字符;
- 引号可以省略,但是省略之后就只能写标识符(按照标识符的要求来,第一个字符不能以数字开头)或者只使用数字;
- 就算引号省略了,键名也还是字符串(这是一个重点,必须要理解并记住)。
用变量作属性名
有些时候,我们需要用变量来做属性名:
let p1 = 'name'
let obj = { p1 : 'frank' }//这样写,对象的属性名为'p1',并不是变量。
let obj = { [p1] : 'frank' } //这样写,对象的属性名为'name'。这时,我们就以一个变量作了对象的属性名。
总结
- 不加[]的属性名,会被自动变为字符串;
- 加了[],则会被当作变量进行求值,然后以求得的值作为对象的属性名,- - 求得的值如果不是字符串,也会自动转变为字符串。
对象的隐藏属性
隐藏属性储存着原型的地址
- JS中,每一个对象都有一个隐藏属性,这个隐藏属性储存着其共有属性组成的对象的地址,这个共有属性组成的对象叫做原型。
- 每一个对象都有原型,原型中存着对象的共有属性;
- 对象的原型也是对象,这个对象的原型也有原型,这个原型包含所有对象的共有属性,是对象的根,为null。
对象属性的增删改查
删除对象属性
delete obj.xxx或者delete obj['xxx']
通过上述两种方式,可以删除对象的xxx属性。
区分两种方式
delete obj.xxx或者delete obj['xxx']
通过这种方式,可以将对象的属性彻底删除,包括属性名以及属性值。
obj.xxx = undefined
通过这种方式,只是将对象的xxx属性的当前的属性值改为了undefined,而并非将该属性完全删除。
如何确认一个属性是否属于某个对象(只有用in操作符)
'xxx' in obj
通过上述API可以判断属性'xxx'是否属于对象obj。若得到的值为true,则表示属性'xxx'属于对象obj;若得到的值为false,则表示该属性不属于对象obj。
通过obj.xxx === undefined并不能判定属性'xxx'是否属于对象obj。
查看对象属性
- 查看所有自身属性
Object.keys(obj)
- 查看自身所有属性的属性名以及属性值,得到的是一系列的数组,每一个属性对应一个数组。
Object.entries(obj)
- 查看自身+共有属性
console.dir(obj)
- 可以判断一个属性'xxx'是否是对象的自身属性。
obj.hasOwnProperty('xxx')
当得到的值为true时,说明'xxx'属性是对象的自身属性;反之,当得到的值为false时,说明该属性有可能是对象的共有属性或者对象中并没有该属性。
'name' in obj和obj.hasOwnProperty('name') 的区别
'name' in obj
用来确定'name'属性是否属于对象obj,但是它无法判断'name'属性是obj的自身属性还是共有属性。
obj.hasOwnProperty('name')
用来确定'name'属性是否是对象obj的自身属性。
查看单个属性
中括号语法
obj['key'] //此时的key是字符串'key'
点语法
obj.key //此时的key是字符串'key'
坑新人语法
obj[key] //此时的key是变量,需要先确认key的值
建议优先使用中括号语法 这样可以保证新手在使用时,不会忘记当前的key是一个字符串,而不是一个变量。
关键知识点
obj.name等价于obj['name'],而不等价于obj[name]
简单来说,obj.name与obj['name']中的name是字符串,而不是变量。
下面是一道帮助我们理解记忆的题目,弄清楚这道题,有助于我们理解上述知识点
代码如下:
let list = ['name', 'age', 'gender'] let person = { name:'frank', age:18, gender:'man'} for(let i = 0; i < list.length; i++){ let name = list[i] console.log(???) }
问题:要使得person的所有属性都被打印出来,问号处应该怎么填写?
A.console.log(person.name)
B.console.log(person[name])
答案是选择B。
因为选项A中的name是一个字符串,所以结果会打印出三遍person的name属性的值;
选项B中的name是一个变量,通过for循环,使得name的值分别为'name'、'age'、'gender',这样就可以将person的三个属性的值都打印出来。
修改或增加对象属性(写属性)
- 可以通过直接赋值进行操作
let obj = {name: 'frank'}
obj.name = 'frank'
obj['name'] = 'frank'
obj['na'+'me'] = 'frank'
let key = 'name'; obj[key] = 'frank'
- 可以进行批量赋值
通过下列API即可对对象的属性进行批量赋值
Object.assign(obj,{name:'frank',age:18,gender:'man'})
上述实例表示给对象obj同时赋值三个属性,包括name、age以及gender。
修改或增加共有属性
无法通过自身修改或增加共有属性
看下列示例:
let obj ={}, obj2 ={} obj.toString = 'xxx'
obj与obj2有着共有属性toString,当执行obj.toString='xxx'时,只是修改了obj自身的属性,而obj2.toString仍然在原型上。
如果我们非要对原型中的属性进行修改时,建议使用:
Object.prototype.toString = 'xxx'
修改对象的原型(一般来说,不要修改原型,会引起很多问题 )
不推荐使用proto去修改对象的原型,一般推荐使用Object.create进行修改。
示例一:(不推荐)
let obj = {name:'frank'}
let obj2 = {name: 'jack'}
let common = {kind: 'human'}
obj.__proto__ = common
obj2.__proto__ = common
复制代码示例二:(推荐,一创建就指定原型)
let obj = Object.create(common)
obj.name = 'frank'
let obj2 = Object.create(common)
obj2.name = 'jack'
复制代码规范的大概意思是,要改就一开始就改,别后来再改,后来改会非常影响性能
查属于读,改和增属于写。查的时候会看原型链,改和增是不会看一个对像的原型链的,改只能改自身,增也只能增自身