JS 心智模型

- Published on

JS 心智模型
人脑无法像电脑一样运转,“心智模型”尽可能帮我们理解代码运行的过程。
JS 的星球世界 ⬇️

6. Object & Function
非原始值(non-primitive values)是让我们创造自己 value 的类型。
6.1 Object
Object和原始值(null, undefined, booleans, numbers, and strings)不同的是:原始值“一直存在”,我们不能"创建"、“修改”和“销毁”他们,我们能做的只有“召唤”(即使用)它们。
但是,我们可以创建一个新的 Object:
// 创建一个新的对象
let arr1 = [1];
// 再创建一个新对象
let arr2 = [];
arr1 === arr2; // false
为什么 arr1 和 arr2 不相等?
因为 arr2 和 arr1 都是新的对象(二者在内存中的地址不同)。
我们可以创建对象,我们可以销毁他们吗?
arr1 = null;
上面的代码意思是:"给变量 arr1 赋值 null" ,我们并没有手动销毁上面创建的对象*[1]*。
销毁*[1]*的是 JS 垃圾回收机制,可惜 JS 的垃圾回收机制对我们是不可感知的。
6.2 Function
- Function 是 value
- Function 也是 表达式
6.2.1 Function 是 value
函数就是 value。我们可以将变量指向它们,就像我们可以处理数字或对象一样。
看一下代码示例:
for (let i = 0; i < 7; i++) {
console.log(2);
}
执行示例中的代码,2这个 value 会被打印 7 次,且每个2都是同一个,因为2是个原始值。
看一下代码示例:
for (let i = 0; i < 7; i++) {
console.log(function () {});
}
执行示例中的代码,log() 方法中的函数同样被执行了 7 次,但是每次都是一个新的 value.
6.2.1 Function 是 表达式
像任何表达式一样,函数表达式是我们 JavaScript 世界的一个“问题” —— 每次我们提问时,它都会通过创建一个新的函数值来回答我们。
小结
我们不能创建、修改、销毁原始值,但是可以创建对象
函数是 value 也是 表达式,它作为表达式被调用时:通过创建一个新的函数值来回答我们
7. JS 中的相等
7.1 相等有三种
- === 代表严格相等,只有相同的两个值结果才为 true
- == 代表非严格相等,JS 会默认先进行类型转换,然后再去比较
- Object.is(), 和 === 相同
示例:
1 === 1; // true
1 === "1"; // false
[] === [];
1 == "1"; // true
Object.is(1, "1"); // false
Object.is(1, 1); // true
7.2 两个特殊情况,需要特别注意一下
- NaN === NaN; -> false
NaN 只有一个,但他们是不等的,记住它吧。
let a = 0 / 0; // a = NaN;
let b = 0 / 0; // a = NaN;
a === b; // false
所以,我们不能用 “a === NaN” 这样的表达式验证 “a” 是不是等于 “NaN”.
可以使用下面 3 种来验证:
Number.isNaN(size);
Object.is(size, NaN);
size !== size; // size 不能是对象
- 0 === -0; -> true
0 和 -0 分别代表两个不同的值,但他们是相等的。
0 === -0; // true
7.3 尽量不要使用“==”
==叫做“松散相等”,它会在两个值不相等时进行转换,然后再次比较。转换规则具体是怎样的??规则是神秘而混乱的。所以,尽量不要这么用,除非在你能掌握的情况下。
console.log([[]] == ""); // true
console.log(true == [1]); // true
console.log(false == [0]); // true
小结
尽量不要用==做判断,应该使用===
Object.is() 和 ===是等效的,除了我们提到的两种情况(NaN 和 -0)
可以用 Number.isNaN(x)检查 x 是否是 NaN
8.属性
8.1 对象作为属性
对象即使作为属性也不存在包裹关系,因为,每个对象都独立存在。
let a = {
b: {
c: "i am c",
},
};
上面代码的心智模型:

可以看出,我们不能想着对象嵌套这样一个模型,如下面是个错误 ❌ 的展示:

8.2 使用对象的属性
使用对象的属性要注意“引用关系”。
对于属性的修改而言,“.” 与 “=” 的作用是大不相同的。🌟
let ilana = {
address: { city: "New York" },
};
let place = ilana.address;
place = { city: "Boulder" };
console.log(ilana.address.city); // New York
let ilana = {
address: { city: "New York" },
};
let place = ilana.address;
place.city = "Boulder";
console.log(ilana.address.city); // Boulder
搞清楚是使用了对象还是使用了对象的属性很重要!🌟🌟
let chip = {
address: { city: "Disneyland" },
};
let dale = {
address: chip.address,
};
let dale1 = {
address: {
// 获取对象 chip 的属性 “address” 的属性 “city”
// 相当于直接获取到字符串“Disneyland”
// address 之后的改变不会对这里产生任何影响 🌟🌟🌟
city: chip.address.city,
},
};
// 重新给对象 chip 的属性 “address” 赋值
chip.address = { city: "Tokyo" };
console.log(dale.address.city); // Tokyo
console.log(dale1.address.city); // Disneyland
总结:
JS 中的原始值不能被我们"创建"、“修改”和“销毁”,我们能做的只有“召唤”(即使用)它们
JS 中的**非原始值(对象)**可以被创建,但同样不可被“修改”和“销毁”
每个对象都是独立的,心智模型里不因该有“嵌套对象”的存在
JS 世界中是值传递而不是变量,不应该在心智模型中将一个变量指向另一个变量,而是应该指向它变量所代表的值
函数是 value 也是 表达式,它作为表达式被调用时:通过创建一个新的函数值来回答我们
尽量用 “===” 而不是 “==”来做逻辑判断,除非在你能掌控的情况下
10. Prototype(原型)
- 任何对象都有个__proto__\属性,指向了它的构造函数的 prototype属性,即指向构造函数的原型对象.
let obj = { teeth: 32, }; console.log(obj.__proto__ === Object.prototype); // true
Object.prototype 心智模型:

- __proto__\没什么神奇的地方,就是一个对象而已,我们通常不会直接使用它,但是访问对象属性时,浏览器会在对象不存在某个属性时去__proto__\上面查找
参考
Dan 神的课程,强烈推荐啊,确实纠正了我的一些问题 👍👍 Learn my JavaScript Mental Models