JS对象
对象就是属性的无序集合,每个属性都是一个名一个值,以键值对的形式存在。
1.1、对象种类
1、内置对象(native object)是由ECMAScript规范定义的对象或类。例如,数组、函数、日期和正则表达式都是内置对象
2、宿主对象(host object)是由JavaScript解释器所嵌入的宿主环境(比如Web浏览器)定义的, 常见的宿主对象有window, document等
3、自定义对象(user-definedobject)是由运行中的JavaScript代码创建的对象。
1.2、创建对象的方式
一、对象直接量化
let a = {
name:" 张总",
sex:"男",
age:18
}
二、通过new指令创建对象
关键字new后跟随一个函数调用。这里的函数称做构造函数,构造函数用以初始化一个新创建的对象。
let a = new Object();创建一个空对象也就是{}
let o = new Array();创建一个空数组也就是[]
let date = new Date();创建一个表示当前时间的Date对象
let r =new RegExp();创建一个可以模式匹配的RegExp对象
1.3访问对象的方式
一、对象属性的查询
可以通过点(.)或方括号([])运算符来获取属性的值
1、 { }.点号的左侧一定得是一个对象, 右侧必须是一个以属性名称命名的简单标识符(即变量, 不是字符串)
2、{ }[ ]方括号的左侧一定得是一个对象, 右侧必须是一个字符串或是可以转换为字符串的(值或者表达式),这个字符串就是属性的名字
两种查询属性值的方法区别:
1、 [ ]运算符可以使用字符串变量的内容作为属性名,点运算符不能
2、中括号法可以用变量作为属性名,而点方法不可以;
3、中括号法可以用数字作为属性名,而点语法不可以;
4、中括号法可以使用js的关键字和保留字作为属性名,而点语法不可以(尽量避免在变量或者属性中使用关键字或保留字this function);有时报错,有时没问题,所以避免
5、遇到字符串属性名称中有空格,特殊字符,使用中括号法,不能用点语法,不用考虑不是字符串带有空格和特殊字符的属性,因为直接报错,没有这么命名的a-x:1,这本身命名方式就是错误的
备注:
在JS中所有的可以由我们自主命名的都可以称为是标识符
- 例如:变量名、函数名、属性名都属于标识符 命名一个标识符时需要遵守如下的规则:
1.标识符中可以含有字母 、数字 、下划线_ 、$符号
2.标识符不能以数字开头
3.标识符不能是ES中的关键字或保留字
4.标识符一般都采用驼峰命名法
- 首字母小写,每个单词的开头字母大写,其余字母小写
helloWorld xxxYyyZzz
二、对象属性的查询错误
查询一个不存在的属性并不会报错,如果在对象o自身的属性或继承的属性中均未找到属性x,属性访问表达式o.x返回undefined
查询一个不存在的对象的属性, 则会直接报错, 并提示开发者你所查询的那个对象没有被定义
1.4对象的属性的常用操作
一、delete运算符可以删除对象的属性。它的操作数应当是一个属性访问表达式。
需要注意,delete只是断开属性和宿主对象的联系,而不会去操作内存中对象的属性的值的存在与否
详细讲解这两段代码区别,事引用类型的指引问题
**第一段代码:**定义了一个a变量,创建了一个嵌套对象{x:{xy:1}},什么意思?就是说创建了一个对象,对象里边属性值是一个对象,所以此嵌套对象相当于创建了两个对象,一个是{x:{xy:1}},一个是{xy:1},而创建的引用类型对象是放在内存中,然后定义了一个b变量,b=a就是说a和b同时指向了{x:{xy:1}}对象,此时a指向对象做了一个操作,删除x属性,此时{x:{xy:1}}就变成了一个空对象,而a和b又同时指向一个对象,所以a和b都是zhixiangl空对象,再控制台显示为{ },如图所示:
第二段代码:同样定义了一个a变量,创建了一个嵌套对象{x:{xy:1}},什么意思?就是说创建了一个对象,对象里边属性值是一个对象,所以此嵌套对象相当于创建了两个对象,一个是{x:{xy:1}},一个是{xy:1},而创建的引用类型对象是放在内存中,然后定义了一个b变量,此时不同的是 b=a.x,相当于指向了对象{xy:1},delete a.x,此时{x:{xy:1}}变成了空对象{ },但是不影响b指向的{xy:1}对象
二、检测对象属性
我们经常会检测集合中成员的所属关系——判断某个属性是否存在于某个对象中。可以通过in运算符、hasOwnProperty() 方法来完成这个工作,甚至仅通过属性查询也可以做到这一点。
检测对象属性之in运算符
in运算符的左侧是属性名(字符串或是一个能够返回字符串的表达式),右侧是对象。如果对象的自有属性或继承属性中包含这个属性则返回true, 不包含则返回false
检测对象属性之hasOwnProperty()
对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性。对于不存在的属性和继承属性它将返回false,参数是字符串类型或者能转换为字符串的表达式
toString是继承属性,返回false
三、枚举对象属性之propertyIsEnumerable()
除了propertyIsEnumerable()检测对象的属性是否存在,我们还会经常遍历对象的属性, 通常使用for/in循环遍历
for/in循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性)
对象继承的内置方法不可枚举的,但在代码中给对象添加的属性都是可枚举的
1.5对象的属性的特性
对象的属性有两种, 分别是数据属性和访问器属性.
一、 数据属性(每个对象的每个属性都有自己的特性,数据属性有4 个描述其行为的特性。)
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4 个描述其行为的特性。
[[Configurable]]:表示能否通过delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。
[[Enumerable]]:表示能否通过for-in循环返回属性。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。
[[Writable]]:表示能否修改属性的值。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。
[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。这个特性的默认值为undefined。
获取对象属性的特性Object.getOwnPropertyDescriptor()
刚刚上边说的数据属性的4个值,对于某个属性都会体现出来
设置对象属性的特性Object.defineProperty()
此方法方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性(修改现有的属性就是修改它的特性,value值啊,或者新增加一个特特性都可以),并返回此对象。
var person={
name:"张名师",
sex:"男",
age:18
}
console.log(Object.getOwnPropertyDescriptor(person,"name"));
for(let i in person){
console.log("属性名称为:"+i+"的值为:"+person[i]);//name,sex,age都输出
}
Object.defineProperty(person,"name",{
enumerable:false// 不能使用分号,可以用逗号,和属性一样是罗列类型
})
console.log(Object.getOwnPropertyDescriptor(person,"name"));
for(let i in person){
console.log("属性名称为:"+i+"的值为:"+person[i]);//name不能输出了,因为设置了enumerable:false,不能枚举遍历了
}
因为name属性的特性enumerable被修改为不能枚举遍历了,所以打印不出来了
此方法这里就是修改了原来的属性(修改属性就是修改它的属性的特性)
var book = {
a:1,
b:2
};
Object.defineProperty(book, "x", {
enumerable:true
})
for(let i in book){
console.log(i);
}
这里此方法就是定义了一个新的属性而不是修改了属性
二、访问器属性(以上属性方法同样可以照用)
访问器属性不包含数据值;它们包含一对儿get 和set 函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用get 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用set 函数并传入新值,这个函数负责决定如何处理数据
访问器属性有如下4 个特性。
[[Configurable]]:表示能否通过delete 删除属性从而重新定义属性,能否修改属性的特 性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为true。
[[Enumerable]]:表示能否通过for-in 循环返回属性。对于直接在对象上定义的属性,这 个特性的默认值为true。
[[Get]]:在读取属性时调用的函数。默认值为undefined。
[[Set]]:在写入属性时调用的函数。默认值为undefined。
访问器属性不能直接定义,必须使用Object.defineProperty()来定义
1.6对象的方法(后续再详细聊)
toString(典型代表)、this指向。。。
又到了说再见的时候了,话说张哥下次我们再见🙂