4.1 对象
构造对象的方法
1 2
| let user = new Object(); let user = {};
|
文本和属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let user = { name: "Randolfluo", "Nian lin": 20 };
alert(user.name);
user.country = "China" alert(user.country);
delete user.country; alert(user.country);
user["Nian lin"] = 18;
|
方括号
1 2 3 4 5 6 7 8
| let user1 = { name: "Randolfluo", age: 20 } let key = prompt("你想知道什么?", "name"); alert(user1[key]);
|
计算属性
我们还可以在运行中输入属性名
1 2 3 4 5 6 7 8 9 10 11 12
| let attr = prompt("Please input a attribute","name");
let human = { attr : "Defalut" };
let value = prompt("Please input a value","Randolfluo");
human[attr]="value: " + value; alert(human[attr]); console.log(attr);
|
属性名简写
如果我们需要通过一个函数创建大量对象,可以这样写
1 2 3 4 5 6 7 8 9 10
| function makeUser(name,age){ return { name, age, }; }
user1 = makeUser("John", 30); user2 = makeUser("Pete", 35); user3 = makeUser("Randolfluo",20);
|
属性存在性测试,in操作符
我们想访问一个属性的值,那么只有该属性存在我们的访问才有意义。
可以通过in
来判断该属性是否存在.
1 2 3 4 5 6 7
| let user = { "name": "Randolfluo", "age": 20 };
alert( "name" in user ); alert( "country" in user );
|
“for..in”循环
可以通过“for..in”循环
遍历对象
1 2 3 4 5 6 7 8 9
| let user = { "name": "Randolfluo", "age": 20 };
for (let key in user){ alert(key); alert(user[key]); }
|
像对象一样排序
获取属性的顺序为:整数属性会被进行排序,其他属性则按照创建的顺序显示。
4.2 对象引用和复制
引用
当一个对象变量被复制 —— 引用被复制,而该对象自身并没有被复制。
1 2 3 4 5
| let user = { name: "Randolfluo" }; let admin = user; admin.name = "God"; alert(user.name); alert(admin.name);
|
使用 const 声明的对象也是可以被修改的。
1 2 3 4 5 6 7
| const user = { name: "John" };
user.name = "Pete";
alert(user.name);
|
复制
使用for…in复制
1 2 3
| for (let key in user) { clone[key] = user[key]; }
|
使用assign复制
1
| let clone = Object.assign({}, user);
|
assign还可以逐个添加不同对象属性
1 2 3
| let permissions1 = {...}; let permissions2 = {...}; Object.assign(user, permissions1, permissions2);
|
垃圾回收
垃圾回收 (javascript.info)
4.4 对象方法,”this”
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| let user = { sayHi3 (){ alert("Hello from sayHi3"); } };
function sayHi1() { alert("Hello from sayHi1"); } user.sayHi1 = sayHi1;
user.sayHi2 = function() { alert("Hello from sayHi2"); };
user.sayHi1(); user.sayHi2(); user.sayHi3();
|
方法中的this
有时候我们需要修改对象的属性,当对象名被修改后我们就无法使用属性.变量
,来访问他,我们可以使用this解决这一问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| let user = { name: "Randolfluo", age: 18,
};
function print(){ alert( this.name); }
let user1 = user; user1.name = "Dick"; user.print = print; user.print(); user1.print = print; user1.print();
let user2 = new User("Jack", 25); user2.name = "Jack"; user.print = print; user.print(); user2.print = print; user2.print();
|
4.5 构造器和操作符 “new”
构造函数
- 它们的命名以大写字母开头。
- 它们只能由
"new"
操作符来执行。
- 用于实现可重用的对象创建代码。
- 在开始时创建了空的
this
,并在最后返回填充了值的 this
。
1 2 3 4 5 6 7 8 9 10 11 12 13
| function User(name, age){ this.name = name; this.age = age; this.print = function(){ alert(this.name + " " + this.age); } };
let Ran = new User("Randolfluo", 20); let Dick = new User("Dick", 18);
Ran.print(); Dick.print();
|
4.6 可选链 “?.”
- 用于解决访问“不存在的属性”的报错的问题
?.
链使我们能够安全地访问嵌套属性。
- 如果
?.
左边部分不存在,就会立即停止运算(“短路效应”)。
访问可能不存在的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let user = { name : "Randolfluo", age : 20 };
alert(user.address.name);
alert(user?.address?.name);
|
?.()和?.[]
可以使用 ?.
来安全地读取或删除,但不能写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| let user1 = { "first name" : "Randolfluo", sayHello(){ alert("Hello"); } };
let user2 = {};
user1.sayHello?.(); user2.sayHello?.();
alert(user1?.["first name"]); alert(user2?.["first name"]);
delete user1?.sayHello;
delete user1?.["first name"]; user1.sayHello?.(); alert(user1?.["first name"]);
user1?.["first name"] = "Randolfluo";
|
4.7 symbol
什么是symbol
- symbol是
全局唯一
的,但是它们的可访问性取决于该模块是否拥有该实例
,如(另一个js文件如果没有从此js文件导入id1和id2,则无法访问这个symbol实例。
- symbol 不会被自动转换为字符串,我们可以使用
toString()
和description
来输出symbol的描述。
1 2 3 4 5 6 7 8
| let id1 = Symbol("id"); let id2 = Symbol("id");
alert(id1 == id2);
alert(id1.toString()); alert(id2.description);
|
通过symbol隐藏属性
1 2 3 4 5 6 7 8 9 10
| let id = Symbol("id");
let User = { [id] : 114514, };
User.id = 12345;
alert(User[id]); alert(User.id);
|
全局 symbol 注册表
- 我们可以在其中创建 symbol 并在稍后访问它们,它可以确保每次访问相同名字的 symbol 时,返回的都是相同的 symbol。
Symbol.for(key)
按描述返回一个 symbol。
Symbol.keyFor(sym)
,通过全局 symbol 返回一个名字
4.8 对象 —— 原始值转换
hint
- 在JavaScript中,类型转换的
“hint”
通常指的是在使用typeof
、instanceof
、in
等操作符时,或者在进行比较操作时,JavaScript引擎是如何解释操作数的。
Symbol.toPrimitive
如果 Symbol.toPrimitive
方法存在,则它会被用于所有 hint
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let user = { name: "John", money: 1000,
[Symbol.toPrimitive](hint) { alert(`hint: ${hint}`); return hint == "string" ? `{name: "${this.name}"}` : this.money; } };
alert(user); alert(+user); alert(user + 500);
|
toString和 valueOf
如果没有 Symbol.toPrimitive
,那么 JavaScript 将尝试寻找 toString
和 valueOf
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let user = { name: "John", money: 1000,
toString() { return `{name: "${this.name}"}`; },
valueOf() { return this.money; }
};
alert(user); alert(+user); alert(user + 500);
|