简介
在javascript中,对象被定义为一组属性的无序集合。即对象是一组没有特定顺序的值。
对象的构成为:属性和方法。一个对象可以拥有多个属性和多个方法。
{
age: 18,
name: "名字是什么",
sayName() {
console.log(this.name);
}
}
对象的属性
一个JavaScript对象中有很多属性。一个对象的属性可以被解释为一个附加到对象上的变量。
属性由一个字符串类型的名字(name)和一个属性描述符(property descriptor)对象构成。
属性的类型
JavaScript中使用一些内部特性来描述属性的特征。开发者不能在JavaScript中直接访问这些特性。规范中用两个中括号把特性的名称括起来,如[[Enumerable]]
属性分两种:数据属性和访问器属性
数据属性【数据】
数据属性包含一个保存数据值的位置。数据属性有四个特性描述它们的行为。
属性描述符 | 解释 | 取值 |
---|---|---|
[[Configurable]] | 1、是否可以通过delete删除并重新定义 2、是否可以修改它的特性 3、是否可以把它改为访问器属性 |
true:默认值 false |
[[Enumerable]] | 是否可以被for-in循环返回 | true:默认值 false |
[[Writable]] | 是否可以被修改 | true:默认值 false |
[[Value]] | 属性实际值 | undefined:默认值 JavaScript中的任意类型 |
数据属性定义
- 直接定义:直接定义属性的时候,以上四种属性描述符都是默认值true。
- 使用
Object.defineProperty()
方法进行精确定义属性及其属性描述符。
Object.defineProperty(对象名, 属性名, 属性描述符(对象))
属性描述符是必须是一个对象,对象中最多有四个属性:configurable
、enumerable
、writable
和value
。如果configurable
、enumerable
、writable
没有指定,将被指定为false
;value
指定为undefined
访问器属性【存储】
访问器属性不包含数据值。相反,它们包含一个获取(get)函数和一个设置(set)函数,不过这两个函数不是必须的。
- 获取函数(get):在读取访问器属性时,被调用;返回一个有效值。
- 设置函数(set):在设置访问器属性时,被调用;设置为传入的 新值。
访问器属性有四个特性描述它们的行为。
属性描述符 | 解释 | 取值 |
---|---|---|
[[Configurable]] | 1、是否可以通过delete删除并重新定义 2、是否可以修改它的特性 3、是否可以把它改为数据属性 |
true:默认值 false |
[[Enumerable]] | 是否可以被for-in循环返回 | true:默认值 false |
[[Get]] | 获取函数,在读取属性时调用 | undefined:默认值 |
[[Set]] | 设置函数,在设置属性时调用 | undefined:默认值 |
访问器属性常常用来设置一些私有属性,从而达到属性的保护。
访问器属性定义
- 访问器属性不能直接定义
- 使用
Object.defineProperty()
定义访问器属性
Object.defineProperty(对象名, 属性名, 属性描述符(对象))
属性描述符中的获取和设置函数不一定都要定义。只定义设置函数,表示不能读取;只定义获取函数,表示只能读取。
定义多个属性
通过Object.defineProperties()
方法定义多个属性及其属性描述符。
Object.defineProperties(对象, {
数据属性: 数据属性的描述符,
...
访问器属性: 访问器属性的描述符
...
})
注意事项
【1】数据属性的configurable
、writable
为false,可以通过访问器属性的set()
方法进行修改。
【2】如果数据属性configurable
、enumerable
、writable
没有指定,将被指定为false
;value
指定为undefined
读取属性的描述符
使用
Object.getOwnPropertyDescriptor()
方法可以取得指定属性的属性描述符。
语法:Object.getOwnPropertyDescriptor(对象名, 属性名)
参数:属性所在对象和对应的属性名。
返回值:一个对象。对于数据属性,返回configuraable
、enumerable
、writable
和value
属性;对于访问器属性,返回configurable
、enumerable
、get
和set
属性。使用
Object.getOwnPropertyDescriptors()
方法可以取得指定属性的属性描述符。
语法:Object.getOwnPropertyDescriptors(对象名)
参数:属性所在对象
返回值:一个对象。对于数据属性,返回configuraable
、enumerable
、writable
和value
属性;对于访问器属性,返回configurable
、enumerable
、get
和set
属性。
访问对象的方式
方式 | 使用 | 样例 |
---|---|---|
点符号 | 属性为有效的JavaScript字符串 | objectName.propertyName |
方括号 | 属性为有效/无效的JavaScript字符串 通过for...in循环遍历对象属性 |
objectName[propertyName变量] |
- 注意事项:
1、对象的名字和属性的名字是大小写敏感的。
2、对象中未赋值的属性的值为undefined
。
3、对象的属性名可以是有效的JavaScript字符串,也可以被转换为字符串的任何类型。
4、对象的属性的值可以是普通变量,也可以是函数。
增强的对象语法
属性简写
给对象添加变量时,属性名和变量名一致,我们可以使用属性简写的进行添加变量。
let name = "名字"
// 之前
let person = {
name: name
}
// 属性简写后
let person = {
name
}
计算属性
计算属性:在[ ]中放入表达式,计算结果可以当做属性名。
这种用法和用方括号访问属性非常类似。
简写方法名
// 未简写
let person = {
sayName: function() {
}
}
// 简写后
let person = {
sayName() {
}
}
注意事项
- 简写方法名对获取函数(get)和设置函数(set)也是适用的。
- 简写方法名可以与计算属性相互兼容
对象解构
对象解构就是使用与对象匹配的结构来实现对象属性的赋值。
展开语法(...):三个点,将对象中的属性全部提取出来。【与数组中的展开语法类似,但有区别】
解构语法(...):将对象中的某些属性从中拿出来。【注意:左边的源数据,右边是声明的变量】解构语法可以解构内置对象中的某些属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
"use strict"
let item = {
name: "hahaha",
sex: "nan"
}
// 展开语法
console.log({
...item
}) // {name: "hahaha", sex: "nan"}
// 解构语法
let {
name: n,
sex: s,
other = "nothing" // 设置默认值
} = item // let {name, sex} = item // 如果名字一致,可以用省略模式
console.log(n) // hahaha
console.log(s) // nan
console.log(other) // nothing
// 变量提前定义,结垢时使用()括起来。
let item_name, item_sex
({
name: item_name,
sex: item_sex,
} = item) // let {name, sex} = item // 如果名字一致,可以用省略模式
console.log(item_name) // hahaha
console.log(item_sex) // nan
// 深层次的解构
let item2 = {
name1: "hahaha",
other1: {
no: "none"
}
}
let {
name1,
other1: {
no
}
} = item2;
console.log(name1) // hahaha
// console.log(other1) // Uncaught ReferenceError: other1 is not defined
console.log(no) // none
// 与解构语法进行区分
let a = "123"
let b = "456"
let opt = {
a1: a,
b1: b
} // let opt = {a, b} // 如果名字一致,可以用省略模式
console.dir(opt)
</script>
</body>
</html>
对象合并
合并的方法:
- 使用展开语法(...)将对象的枚举属性赋值到一个新的对象上。
- 使用Object.assgin()方法进行对象的赋值。【Object.assign()进行对象复制的时候是浅复制】
Object.assign() | 展开语法 | |
---|---|---|
使用场景 | 复制对象 对象拷贝 |
复制对象 对象拷贝 |
枚举 | 可枚举 | 可枚举 |
原型链 | 不触发,即使原型链上是可枚举的属性 | 不触发,即使原型链上是可枚举的属性 |
区别 | 会触发setter | 不会触发setter |
对象的方法
一个方法是关联到某个对象的函数,或者简单说,一个方法是一个值为某个函数的对象属性。定义方法就像定义普通的函数,然后赋值给对象的某个属性。
方法的定义有两种方式:
// 常规方式
var obj = {
foo: function() {
/* code */
},
bar: function() {
/* code */
}
};
// 方法名简写方式
var obj = {
foo() {
/* code */
},
bar() {
/* code */
}
};
Object中的静态方法
Object.assgin()
- 作用:进行对象的复制【浅拷贝】
- 语法:Object.assign(目标对象, 多个源对象)
- 返回值:返回合并后的对象,与目标对象相等。
- 底层:使用源对象的[[Get]]取的属性的值,使用目标对象的[[Get]]设置属性的值。
注意事项
1、复制以字符串和符号为键的属性。
2、Object.assgin()该方法是浅拷贝。
3、如果多个源对象有相同的属性,则使用最后一个复制的值。
Object.is()
- 作用:进行对象的判断
- 语法:Object.is(对象1,对象2)
- 返回值:如果相等,返回true;否则返回false。
注意事项
1、该方法与===
的作用类型
2、参数可以是基本数据类型
Object.defineProperty()
- 作用:给某个对象添加单个属性,同时设置属性的描述符
- 语法:Object.defineProperty(对象, 属性名, 属性描述符)
注意事项
1、属性描述符必须是一个对象
Object.defineProperties()
- 作用:给某个对象同时添加多个属性,同时设置属性的描述符
- 语法:Object.defineProperties(对象, 属性名及属性描述符)
注意事项
1、第二个参数的形式如下,属性描述符必须是一个对象。
{
属性一: 属性描述符,
...
}
Object.getOwnPropertyDescriptor()
- 作用:获取某个对象中某个属性的属性描述符
- 语法:Object.getOwnPropertyDescriptor(对象, 属性名)
- 返回值:返回一个对象。如果是数据属性,返回
configurable
、enumerable
、writable
、value
;如果是访问器属性,返回configurable
、enumerable
、get
、set
。
Object.getOwnPropertyDescriptors()
- 作用:获取某个对象中某个属性的属性描述符
- 语法:Object.getOwnPropertyDescriptor(对象)
- 返回值:返回一个对象。如果是数据属性,返回
configurable
、enumerable
、writable
、value
;如果是访问器属性,返回configurable
、enumerable
、get
、set
。
对象引用
对象和函数、数组一样是引用类型,即复制只会复制引用地址。
对象作为函数的形参,实际上传递的是对象的地址
this
this
关键字表示当前对象
对象的遍历
枚举一个对象的属性
以下方法受到enumerable
和原型链
的影响。
方法 | for...in循环 | Object.keys(o) | Object.getOwnPropertyNames(o) | Object.getOwnPropertySymbols(o) |
---|---|---|---|---|
含义 | 返回对象及原型链上可枚举的属性 | 返回自身的所有可枚举属性 | 返回自身所有属性 | 返回自身所有的Symbols属性 |
是否可枚举 | 可 | 可 | 不关心 | Symbol |
是否访问原型链 | 访问 | 不访问 | 不访问 | 不访问 |
是否访问Symbol | 不访问 | 不访问 | 不访问 | 访问 |
for...in
作用:以任意顺序遍历一个对象的除Symbol以外的可枚举属性【包含原型链上可枚举的属性】
Object.keys()
作用:返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
Object.values()
作用:返回一个给定对象自身的所有可枚举属性值的数组。
Object.entries()
作用:返回一个给定对象自身可枚举属性的键值对数组
Object.getOwnPropertyNames()
作用:返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
Object.getOwnPropertySymbols()
作用:返回一个给定对象自身的所有 Symbol 属性的数组。
对象的继承
所有的JavScript对象至少继承于一个对象,被继承的对象被称为原型。
每个对象可以通过构造函数的prototype
属性找到原型 或 每个实例对象有一个私有属性__proto__
指向原型
获取对象原型
方法一:Object.getPrototypeOf()
方法返回指定对象的原型。
方法二:实例化对象.__proto__
Object.getPrototypeOf(object)
- 参数
obj:要返回其原型的对象 - 返回值
给定对象的原型,如果没有继承属性,则返回null
设置或修改对象原型
方法一:Object.create()
创建对象的时候指定原型.
方法二:Object.prototype.__proto__
方法三:Objcet.setPrototypeOf()
方法四:Reflect.setPrototypeOf()
Object.create(proto, propertiesObject)
:
- 参数:
proto:新创建对象的原型对象
propertiesObject:可选 - 返回值
一个新对象,带着指定的原型对象的属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
"use strict"
// Shape - 父类(superclass)
function Shape() {
this.x = 0;
this.y = 0;
}
// 父类的方法
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this); // call super constructor.
}
// 子类续承父类,以下两句话一般同时存在
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
console.dir(rect) // rect --> Rectangle---->Shape---->Object
</script>
</body>
</html>
Objcet.setPrototypeOf(obj, prototype)
- 参数:
obj:设置其原型对象
prototype:对象的新原型(对象或null) - 过程:
如果对象的原型被修改成不可扩展(通过Object.isExtensible()
)的,则抛出TypeError异常。
如果prototype新原型参数不是对象或努力了,则什么也不做。
否则,该方法修改对象的原型。
Reflect.setPrototypeOf(target, prototype)
- 参数:
target:设置其原型对象
prototype:对象的新原型(对象或null) - 返回值:
返回一个boolean类型表明是否原型已经设置成功。 - 过程:
如果参数target不是Object,或者prototype既不是对象,也不是null,则抛出TypeError异常。
Object原型与属性相关的方法
方法 | 作用 | 参数 | 返回值 |
---|---|---|---|
obj.hasOwnProperty() | 判断属性是否在某个对象自身上 {不含原型链} | prop:要检测的属性 | true:有 false:无 |
prop in obj | 判断属性是否在某个对象上 {含原型链} | prop:要检测的属性 | true:有 false:无 |
prototypeObj.isPrototypeOf(obj) | 测试一个对象是否在另一个对象的原型链上 | object:在该对象的原型链上搜寻 | true:在 false:不 |
instanceof操作符 | 检测构造函数的prototype属性是否会出现在某个实例对象的原型链上 | 操作符,不是函数 | true:在 false:不在 |
obj.propertyIsEnumerable(prop) | 判断属性名是否可枚举 | prop需要测试的属性 | true:枚举 false:非枚举 |