对象进阶篇

创建对象

1.对象字面量

对象字面量是一个表达式,每次运算都会创建一个新的对象,其中的属性值也会重新计算。

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",
  },
};

2.通过new创建对象

通过new调用构造函数(constructor)来创建并初始化一个新对象。

JavaScript语言核心中的原始类型都包含内置构造函数,如Object()、Array()、Date()等。

原型:

通过new和构造函数创建的对象的原型就是构造函数的prototype属性引用的对象。 如:new Array()对象的原型就是Array.prototype。

所有内置构造函数都具有一个继承自Object.prototype的原型。

如:Array.prototype的属性继承自Object.prototype。 通过层级的原型继承形成的链接,称为“原型链”(prototype chain)。

let obj = { value: 100 };
Object.prototype.flag = "head";
console.log(obj.flag);
let arr = [1, 2, 3, 4];
console.log(arr.flag);

3.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);

访问对象属性

let author = {
  "first name": "Tonny",
  "last-name": "Michael",
  age: 40,
};
console.log(author["first name"], author["last-name"]);
let { "first name": fname, "last-name": lname } = author;
console.log(fname, lname, author.age);

属性访问错误

查询一个不存在的属性并不会报错,如果在对象o自身的属性或继承的属性中均未找到属性x,属性访问表达式o.x返回undefined。

但是,如果对象不存在,那么试图查询这个不存在的对象的属性就会报错。

let one = {};
// let one = { two: { three: 3 } };
console.log(one.two.three);
if (one) {
  if (one.two) {
    if (one.two.three) console.log(one.two.three);
  }
}
console.log(one && one.two && one.two.three);
console.log(one?.two?.three); // Null传导运算符

 在这些场景下给对象o设置属性p会失败:

o中的属性p是只读的:不能给只读属性重新赋值(defineProperty()方法中有一个例外,可以对可配置的只读属性重新赋值)。

o中的属性p是继承属性,且它是只读的:不能通过同名自有属性覆盖只读的继承属性。

o中不存在自有属性p:o没有使用setter方法继承属性p,并且o的可扩展性(extensible attribute)是false。如果o中不存在p,而且没有setter方法可供调用,则p一定会添加至o中。但如果o不是可扩展的,那么在o中不能定义新属性。

 删除属性

delete运算符可以删除对象的属性。

它的操作数应当是一个属性访问表达式。

delete只是断开属性和宿主对象的联系,而不会去操作属性中的属性。

delete运算符只能删除自有属性,不能删除继承属性。 要删除继承属性必须从定义这个属性的原型对象上删除它,而且这会影响到所有继承自这个原型的对象。

delete不能删除那些可配置性为false的属性。 某些内置对象的属性是不可配置的,比如通过变量声明和函数声明创建的全局对象的属性。

{
let auth = book.author;
delete book.author;
console.log(book, auth);
}

{
let o = { x: 1 };
delete o.x;
delete o.toString;
console.log(o, o.toString());
}

 检测属性

判断某个属性是否存在于某个对象中,可以通过in运算符、hasOwnPreperty()和propertyIsEnumerable()方法,甚至也可以仅通过属性查询。

let o = { x: 1 };

console.log("x" in o);
console.log("y" in o);
console.log("toString" in o);

console.log(o.hasOwnProperty("x"));
console.log(o.hasOwnProperty("y"));
console.log(o.hasOwnProperty("toString"));

console.log(o.propertyIsEnumerable("x"));
console.log(o.propertyIsEnumerable("y"));
console.log(o.propertyIsEnumerable("toString"));
console.log(Object.prototype.propertyIsEnumerable("toString"));

 枚举属性

for/in循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量。

对象继承的内置方法不可枚举的,但在代码中给对象添加的属性都是可枚举的。

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]);
}
//Object.keys(),它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。
let o = Object.create({ m: 10, n: 20 });
o.x = 1; o.y = 2; o.z = 3;
console.log(Object.keys(o));

//Object.getOwnPropertyNames()和Ojbect.keys()类似,只是它返回对象的所有自有属性的名称,而不仅仅是可枚举的属性。
let o = Object.create({ m: 10, n: 20 });
o.x = 1; o.y = 2; o.z = 3;
console.log(Object.getOwnPropertyNames(o));

 getter和setter

当程序查询存取器属性的值时,JavaScript调用getter方法(无参数)。 这个方法的返回值就是属性存取表达式的值。

当程序设置一个存取器属性的值时,JavaScript调用setter方法,将赋值表达式右侧的值当做参数传入setter。

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);
circle.round = 60;
console.log(circle.r, circle.area);


let circle1 = Object.create(circle);
circle1.r = 20;
console.log(circle1.round);
circle1.round = 500;
console.log(circle1.r, circle1.area);

 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() 返回给定对象自身可枚举值的数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值