前言
JavaScript基础部分,学习笔记
源网站:javascript.info
1 对象
1.1 对象的属性值简写
可以用 name 来代替 name:name 像下面那样:
function makeUser(name, age) {
return {
name, // 与 name: name 相同
age, // 与 age: age 相同
// ...
};
}
我们可以把属性名简写方式和正常方式混用:
let user = {
name, // 与 name:name 相同
age: 30
};
1.2 属性存在性测试,"in"操作符
检查属性是否存在
let user = { name: "John", age: 30 };
alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。
1.3 "for…in"循环
对象可以用for…in
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// keys
alert( key ); // name, age, isAdmin
// 属性键的值
alert( user[key] ); // John, 30, true
}
1.4 总结
对象,是具有特殊特性的关联数组
- 属性的键,必须是字符串或者symbol
- 值可以是任何类型
访问属性:
- 点符号:
obj.property
- 方括号:
obj["property"]
对象包含:
- Array
- Date
- Error
- 等等
2 对象引用和复制
2.1 引用
let objectA = objectB
是引用
把含有对象地址的一张纸传递给对方,实际上地址空间是同一块
2.2 克隆与合并
用Object.assign
2.2.1合并多个对象
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// 将 permissions1 和 permissions2 中的所有属性都拷贝到 user 中
Object.assign(user, permissions1, permissions2);
// 现在 user = { name: "John", canView: true, canEdit: true }
2.2.2 覆盖已有属性
let user = { name: "John" };
Object.assign(user, { name: "Pete" });
alert(user.name); // 现在 user = { name: "Pete" }
2.3 深层克隆
如果包含多层对象的对象,需要克隆
用lodash库的_.cloneDeep(obj)
3 垃圾回收
“2 对象引用和复制”中已经讲了其内存方式
那么,如果一块存储区域,不再被任何一处使用,即没有人此时掌握一张写着这块内存的地址是什么的纸的话,那么这块内存就会被回收,因为没人可以去那儿了
4 对象方法,“this”
此处只要简单会使用即可,后续有章节会更深入介绍箭头函数
在此处需知道,箭头函数没有自己的"this"
而除此以外,关于this并没有什么需要多讲的,日常已经用得很多了
5 构造器和操作符"new"
就是,创建一个构造函数来new不止一个对象
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
that’s all
6 可选链"?."
访问对象的属性,如果该属性不存在,就会出现error
但我们不希望出现error,于是就有了可选链
可选方法也是同理
如果可选链?.
前面的值为 undefined
或者null
,它会停止运算并返回 undefined
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
值得注意的是:
1 ?.
语法使其前面的值成为可选值,但不会对其后面的起作用。
例如,在user?.address.street.name
中,?.
允许 user
为 null/undefined
(在这种情况下会返回 undefined
)也不会报错,但这仅对于user
。更深层次的属性是通过常规方式访问的。如果我们希望它们中的一些也是可选的,那么我们需要使用更多的?.
来替换 .
2 对于方法
let userAdmin = {
admin() {
alert("I am admin");
}
};
let userGuest = {};
userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // 啥都没有(没有这样的方法)
?.
同样是判断其之前的内容是否存在,但()
应在?.
之后
7 Symbol类型
建议阅读原文:Symbol类型
贴个总结在这里:
不是很懂,实际中也暂时还没用到过,后续如果有了现实的使用场景,会再补充一篇博客。
8 对象 - 原始值转换
简单来说,举个例子,就是string类型和String对象这,这样的转换。触发的情景是对象运算比如obj1 + obj2
,obj1 - obj2
或者打印alert(obj)
时
转换算法是:
- 调用
obj[Symbol.toPrimitive](hint)
如果这个方法存在, - 否则,如果
hint
是"string"
尝试obj.toString()
和obj.valueOf()
,无论哪个存在。 - 否则,如果
hint
是"number"
或者"default"
尝试obj.valueOf()
和obj.toString()
,无论哪个存在。
在实践中,为了便于进行日志记录或调试,对于所有能够返回一种“可读性好”的对象的表达形式的转换,只实现以 obj.toString() 作为全能转换的方法就够了。
由于,都说了“只实现obj.toString()作为全能转换的方法就够了”,这里就不详细说其他的转换方法了,如有需要,详情见原文:对象 - 原始值转换