ZHANGYU.dev

October 14, 2023

《你不知道的JavaScript》(上卷)笔记

JavaScript3.2 min to read

异常

作用域

查找

动态更改作用域的方法

由于引擎无法优化,并且在严格模式下也是禁用的,所以不要使用它们

var,let,const

var a = 1;
function foo() {
    console.log(this.a); // 1
}

const a = 1;
function foo() {
    console.log(this.a); // undefined
}

this

function foo() {
    console.log(this.a);
}

function doFoo(fn) {
    // fn其实引用的foo
    fn(); // <-- 调用位置
}

var obj = {
    a: 2,
    foo: foo,
};

var a = "oops,global"; // a是全局对象的属性

doFoo(obj.foo); // "oops,global"

虽然obj.foo通过了隐式绑定,但是在调用过程中,传入的实际是obj.foo的引用,引用的是foo函数本身,在调用时fn()是一个不带任何修饰的函数调用,因此应用了默认绑定

优先级

new > 显式绑定 > 隐式绑定 > 默认绑定

赋值表达式

let a,
    b = () => {};
console.log((a = b));

赋值表达式会返回等号右边的值

不变性

所有的不变性方法都是浅不变的,如值是数组能修改数组内的元素

[[Get]]和[[Put]]

[[Get]]

obj.a其实是实现了[[Get]]操作,有点像函数调用:[[Get]](),如果在对象中查找到名称相同的属性,就会返回这个属性的值,否则就会遍历可能存在的[[Prototype]]链,如果无论如何都没有找到名称相同的属性,就会返回undefined;

[[Put]]

[[Put]]被触发时,实际的行为取决于许多因素,包括对象中是否已经存在这个属性(这是最重要的因素)

如果你希望在不存在的第二种和第三种的情况下也屏蔽原型链上层的同名属性,那就不能用=操作符来赋值,而是使用Object.defineProperty()

存在性

const obj = {};
Object.defineProperty(obj, "a", { enumerable: true, value: 2 });
Object.defineProperty(obj, "b", { enumerable: false, value: 2 });

("a" in obj)(
    // true
    "b" in obj
); // true

obj.hasOwnProperty("a"); // true
obj.hasOwnProperty("b"); // true

for (let k in obj) {
    console.log(k, obj[k]);
}
// "a" 2

obj.propertyIsEnumerable("a"); // true
obj.propertyIsEnumerable("a"); // false

Object.keys(obj); // ["a"]
Object.getOwnPropertyNames(obj); // ["a","b"]

读到继承、类的时候就草草的读完了,Js 中的类太难以让人理解了,__protp__,prototype,舍弃对象...什么的,感觉实际使用中并不太会深入的使用类,所以这部分没有细度,之前看的高设上的有些内容也忘记了,毕竟有了class,谁还会去写 es5 风格的类呢