文章目录
前言
此系列文章用于记录小萌新的ES6的学习经历如有什么错误或者不好的地方请各位大佬多多指教
一、对象的特征
1.1.基本概念与特征
Javascript对象可以看作是一个有很多个属性的无序集合。每个属性都是一个键值对。
对象的属性值是任意的Javascript值,或者是一个setter或者getter函数。
并且每个属性都有自己的特征,其中包括:
- 可写(writable attribute),表明是否可以设置属性的值。
- 可枚举(enumerable attribute),表明是否可以通过for/in结构返回该属性。
- 可配置(configurable attribute),表明是否可以删除或修改该属性。
每个对象还有三个基本的对象特征:
- 对象的原型(prototype),指向另一个对象,该对象的属性会被当前对象继承。
- 对象的类(class),一个标识对象类型的字符串。
- 对象的扩展标记(extensible flag),指明了是否可以向该对象添加新属性。
代码如下(示例):
{
let empty = {}; //没有任何属性的对象
let point = { x: 0, y: 0 }; //具有属性的对象
let book = {
//属性名中有空格,必须用字符串表示。
"main title": "JavaScript",
//属性名中有特殊字符,必须用字符串表示
"sub-title": "The Definitive Gruide",
//属性名可以是保留字,但尽量避免。
for: "all audiences",
//属性值可以是一个对象。
author: {
firstname: "David",
lastname: "Flanagan",
},
};
}
1.2.对象的创建
每一个Javascript对象都有一个原型对象,并且会从原型对象上去继承属性。
原型(也可以说是对象的父亲或者爷爷)
所有内置构造函数都具有一个继承自Object.prototype的原型。
- 如:Array.prototype的属性继承自Object.prototype。
- 通过层级的原型继承形成的链接,称为“原型链”(prototype chain)。
代码如下(示例):
{
let obj = { value: 100 };
Object.prototype.flag = "head";
console.log(obj.flag); // head
let arr = [1, 2, 3, 4];
console.log(arr.flag); // head
}
在顶级原型上进行属性的扩展所有通过字面量和内置的对象都会获得该顶级原型的所有属性。
**
Object.create( )
**此方法可以把括号中的对象当作原型给到左边赋予的对象。(简而言之就是给一个对象指定一个原型对象)
代码如下(示例):
{
// obj1继承了属性x和y。
let obj1 = Object.create({ x: 1, y: 2 });
//obj2不继承任何属性和方法。
let obj2 = Object.create(null);
//obj3是一个普通的空对象。
let obj3 = Object.create(Object.prototype);
console.log(obj1.x); //1
console.log(obj3.x); //此对象就是平时普通创建的空对象一样没有其他属性
}
二、对象属性
2.1.属性访问
首先对于一个对象属性可以使用字符串
或者引用值
进行命名。
代码如下(示例):
{
let author = {
"first name": "Tonny",
"last-name": "Michael",
age: 40,
};
console.log(author["first name"], author["last-name"]); //Tonny Michael
let { "first name": fname, "last-name": lname } = author;
console.log(fname, lname, author.age); //Tonny Michael 40
}
- 针对字符串的对象必须使用
方括号
的方式进行访问, - 而通过引用值进行命名的属性可以使用
方括号
进行访问并且还可以使用.(点)
的方式进行访问。
2.2.删除属性
删除属性可以是用delete
关键字进行属性的删除但需要注意的是:
- delete只是断开属性和宿主对象的联系,如果我的属性的值是一个另一个对象的属性,则
delete
不会去操作属性中的属性。 - 删除属性只能删除自己的属性,不嫩删除继承来的属性(自己原型上的属性)。
代码如下(示例):
{
let o = { x: 1 };
delete o.x;
delete o.toString;
console.log(o, o.toString()); // {} [object Object]
}
2.3.检测属性
使用以下一些方式可以检测该对象有没有该属性:
- 可以通过in运算符:该方法会包含自身和自己所继承的所有属性里面进行查找
- hasOwnPreperty():该方法不会包含自己继承的属性。
- propertyIsEnumerable()方法:该方法不会包含自己继承的属性。
- 甚至也可以仅通过属性查询。
代码如下(示例):
{
let o = { x: 1 };
console.log("x" in o); //true
console.log("y" in o); //false
console.log("toString" in o); //true
console.log(o.hasOwnProperty("x")); //true
console.log(o.hasOwnProperty("y")); //false
console.log(o.hasOwnProperty("toString")); //false
console.log(o.propertyIsEnumerable("x")); // true
console.log(o.propertyIsEnumerable("y")); //false
console.log(o.propertyIsEnumerable("toString")); //flase
console.log(Object.prototype.propertyIsEnumerable("toString")); //false
}
2.4.枚举属性
有三种方式对对象进行枚举具体方法如下:
for...in...
循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量。Object.keys()
它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。Object.getOwnPropertyNames()
它和Ojbect.keys()类似,只是它返回对象的所有自有属性的名称,而不仅仅是可枚举的属性。
代码如下(示例):
{
let o = Object.create({ m: 10, n: 20 });
o.x = 1; o.y = 2; o.z = 3;
for (let p in o) {
console.log(p, o[p]);
/*
x 1
y 2
z 3
m 10
n 20
*/
{
let o = Object.create({ m: 10, n: 20 });
o.x = 1; o.y = 2; o.z = 3;
console.log(Object.keys(o)); //[ 'x', 'y', 'z' ]
}
{
let o = Object.create({ m: 10, n: 20 });
o.x = 1; o.y = 2; o.z = 3;
console.log(Object.getOwnPropertyNames(o)); //[ 'x', 'y', 'z' ]
}
}
可以看出来for in的方式把自身和继承来的所有可枚举的属性进行了遍历,keys这种方式只是遍历了所有自身的可枚举的属性,而最后一种方法能把自身的所有属性进行遍历(包括枚举和不可枚举的)。
2.4.属性getter和setter
属性的getter
和setter
关键字类似Java
中的读取器和存储器,这两个属性可以对自身的一些属性在读取和设置的时候进行一些操作。
代码如下(示例):
{
let circle = {
r: 10,
get round() {
return 2 * this.r * Math.PI;
},
set round(v) {
this.r = v / 2 / Math.PI;
},
get area() {
return Math.PI * this.r ** 2;
},
};
console.log(circle.round, circle.area); //62.83185307179586 314.1592653589793
circle.round = 60;
console.log(circle.r, circle.area); //9.549296585513721 286.47889756541167
let circle1 = Object.create(circle);
circle1.r = 20;
console.log(circle1.round); //125.66370614359172
circle1.round = 500;
console.log(circle1.r, circle1.area); //79.57747154594767 19894.367886486918
}
2.5.属性的特征
首先在前面提到属性一共有三个特征分别是:
- 可写(writable attribute),表明是否可以设置属性的值。
- 可枚举(enumerable attribute),表明是否可以通过for/in结构返回该属性。
- 可配置(configurable attribute),表明是否可以删除或修改该属性。
代码如下(示例):
{
let o = {};
Object.defineProperty(o, "x", {
value: 10,
writable: true,
enumerable: false,
configurable: false,
});
console.log(o.x, Object.keys(o));
}
可以通过Object.defineProperty()
方法进行属性的特征进行配置。
三、Object构造函数的方法
下面是object的全部方法,比较常用的方法我把它加粗了可以重点看一下。
这是全部方法的地址:Object全部方法。
方法 | 描述 |
---|---|
Object.assign() | 通过复制一个或多个对象来创建一个新的对象。 |
Object.create() | 使用指定的原型对象和属性创建一个新对象。 |
Object.defineProperty() | 给对象添加一个属性并指定该属性的配置。 |
Object.defineProperties() | 给对象添加多个属性并分别指定它们的配置。 |
Object.entries() | 返回给定对象自身可枚举属性的 [key, value] 数组。 |
Object.freeze() | 冻结对象:其他代码不能删除或更改任何属性。 |
Object.getOwnPropertyDescriptor() | 返回对象指定的属性配置。 |
Object.getOwnPropertyNames() | 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。 |
Object.getOwnPropertySymbols() | 返回一个数组,它包含了指定对象自身所有的符号属性。 |
Object.getPrototypeOf() | 返回指定对象的原型对象。 |
Object.is() | 比较两个值是否相同。所有 NaN 值都相等(这与和=不同)。 |
Object.isExtensible() | 判断对象是否可扩展。 |
Object.isFrozen() | 判断对象是否已经冻结。 |
Object.isSealed() | 判断对象是否已经密封。 |
Object.keys() | 返回一个包含所有给定对象自身可枚举属性名称的数组。 |
Object.preventExtensions() | 防止对象的任何扩展。 |
Object.seal() | 防止其他代码删除对象的属性。 |
Object.setPrototypeOf() | 设置对象的原型(即内部 [[Prototype]] 属性)。 |
Object.values() | 返回给定对象自身可枚举值的数组。 |
总结
本文主要讲述了ES6中的对象进阶方面如果又不好的地方希望大家多多提意见。