
获得徽章 8
- "谦虚使人进步,骄傲使人落后。" - "Humility is the key to progress; arrogance is the door to regression." - Chinese Proverb等人赞过14
- #每天一个知识点# defineProperty和proxy的区别?
Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。并 劫持各个属性 getter 和 setter,在数据变化时发布消息给订阅者,触发相应的监听回调,而这之间存在几个问题
初始化时需要遍历对象所有 key,如果对象层次较深,性能不好
通知更新过程需要维护大量 dep 实例和 watcher 实例,额外占用内存较多
Object.defineProperty 无法监听到数组元素的变化,只能通过劫持重写数方法
动态新增,删除对象属性无法拦截,只能用特定 set/delete API 代替
不支持 Map、Set 等数据结构
Vue3 使用 Proxy 来监控数据的变化。Proxy 是 ES6 中提供的功能,其作用为:用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。相对于Object.defineProperty(),其有以下特点:
Proxy 直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。
它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
Proxy 可以监听数组的变化。展开赞过评论2 - #每天一个知识点# 哪一个是正确的?
const bird = {
size: 'small'
}
const mouse = {
name: 'Mickey',
small: true
}
A: mouse.bird.size是无效的
B: mouse[bird.size]是无效的
C: mouse[bird["size"]]是无效的
D: 以上三个选项都是有效的
答案: A
在 JavaScript 中,所有对象的 keys 都是字符串(除非对象是 Symbol)。尽管我们可能不会定义它们为字符串,但它们在底层总会被转换为字符串。
当我们使用括号语法时([]),JavaScript 会解释(或者 unboxes)语句。它首先看到第一个开始括号 [ 并继续前进直到找到结束括号 ]。只有这样,它才会计算语句的值。
mouse[bird.size]:首先计算 bird.size,这会得到 small。mouse["small"] 返回 true。
然后使用点语法的话,上面这一切都不会发生。mouse 没有 bird 这个 key,这也就意味着 mouse.bird 是 undefined。然后当我们使用点语法 mouse.bird.size 时,因为 mouse.bird 是 undefined,这也就变成了 undefined.size。这个行为是无效的,并且会抛出一个错误类似 Cannot read property "size" of undefined。展开赞过51 - #每天一个知识点# 输出是什么?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1)
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1)
}
选项:
A: 0 1 2 和 0 1 2
B: 0 1 2 和 3 3 3
C: 3 3 3 和 0 1 2
答案:C
由于 JavaScript 的事件循环,setTimeout 回调会在遍历结束后才执行。因为在第一个遍历中遍历 i 是通过 var 关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符 ++ 来每次递增 i 的值。当 setTimeout 回调执行的时候,i 的值等于 3。
在第二个遍历中,遍历 i 是通过 let 关键字声明的:通过 let 和 const 关键字声明的变量是拥有块级作用域(指的是任何在 {} 中的内容)。在每次的遍历过程中,i 都有一个新值,并且每个值都在循环内的作用域中展开赞过11 - #每天一个知识点# 下面代码输出是什么?
function sayHi() {
console.log(name)
console.log(age)
var name = 'Lydia'
let age = 21
}
sayHi()
选项:
A: Lydia 和 undefined
B: Lydia 和 ReferenceError
C: ReferenceError 和 21
D: undefined 和 ReferenceError
答案: D
在函数内部,我们首先通过 var 关键字声明了 name 变量。这意味着变量被提升了(内存空间在创建阶段就被设置好了),直到程序运行到定义变量位置之前默认值都是 undefined。因为当我们打印 name 变量时还没有执行到定义变量的位置,因此变量的值保持为 undefined。
通过 let 和 const 关键字声明的变量也会提升,但是和 var 不同,它们不会被初始化。在我们声明(初始化)之前是不能访问它们的。这个行为被称之为暂时性死区。当我们试图在声明之前访问它们时,JavaScript 将会抛出一个 ReferenceError 错误。展开等人赞过55