null 和 undefined 的区别,如何让一个属性变为 null?
undefined: 是全局的一个属性,当一个变量没有被赋值或者一个函数没有返回值或者某个对象不存在某个属性却去访问或者函数定义了形参但没有传递实参,这时候都是undefined。undefined用typeof判断为‘undefined’,其中undefined==undefined、undefined===undefined。
null: 代表对象的值未设置,相当于一个对象没有设置指针地址就是null。null通过typeof判断为‘object’。null === null、null == null、null == undefined、null!== undefined。undefined表示一个变量初始状态值,而null则表示一个变量被人为的设置为空对象,而不是原始状态。
注意: 在实际使用过程中,不需要对一个变量显式的赋值undefined,当释放一个对象的时候,直接赋值为null即可。让一个变量为null,直接给该变量赋值为null就可以。
promise.race、promise.all、promise.allSettled 有哪些区别?、
Promise.all-(所有成功)
处理结果:
所有成功才返回数组。如果任何一个Promise失败,那么整个Promise链将立即终止并返回错误原因。
功能: 接受一个 Promise 对象的可迭代对象(通常是数组),并返回一个新的 Promise 对象。这个新的 Promise 对象在所有输入的 Promise 对象都成功时成功,并返回一个包含所有成功 Promise 结果的数组。如果其中任何一个 Promise 失败,则立即失败,并返回第一个失败的 Promise 的拒绝理由。
返回值: 一个 Promise 对象。成功时,返回一个数组,其中包含每个输入 Promise 对象的结果;失败时,返回第一个失败的 Promise 的拒绝原因。
使用示例:
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(results => {
console.log(results); // [1, 2, 3]
}).catch(error => {
console.error(error);
});
Promise.race-(谁快谁赢)
处理结果:
谁先执行,就返回。这意味着只要其中一个Promise完成(无论是成功还是失败),整个Promise链就会结束并返回相应的结果或错误原因。
功能:接受一个 Promise 对象的可迭代对象(通常是数组),并返回一个新的 Promise 对象。这个新的 Promise 对象将会在第一个输入的 Promise 对象解决或拒绝时解决或拒绝,而不管其他 Promise 对象的状态。
返回值:一个 Promise 对象。它的状态由第一个解决或拒绝的 Promise 决定。
使用示例:
Promise.race([
new Promise((resolve) => setTimeout(resolve, 500, 'first')),
new Promise((resolve) => setTimeout(resolve, 100, 'second'))
]).then(result => {
console.log(result); // 'second' (因为它首先解决)
});
Promise.allSettled-(全盘接收)
处理结果:
所有执行完毕后才返回。无论成功还是失败,都会返回一个包含所有Promise状态和值/原因的对象数组。
功能:接受一个 Promise 对象的可迭代对象(通常是数组),并返回一个新的 Promise 对象。这个新的 Promise 对象在所有输入的 Promise 对象都完成时解决(无论成功还是失败),并返回一个数组,其中每个元素是一个对象,描述了对应 Promise 对象的结果或拒绝原因。
返回值:一个 Promise 对象。成功时,返回一个包含每个输入 Promise 对象的结果的数组,每个结果对象有两个属性:status("fulfilled" 或 "rejected")和 value(如果成功)或 reason(如果失败)。
使用示例:
Promise.allSettled([
Promise.resolve(1),
Promise.reject(new Error('Failed')),
Promise.resolve(3)
]).then(results => {
console.log(results);
/*
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: Error('Failed') },
{ status: 'fulfilled', value: 3 }
]
})
## 虚拟 dom 原理是啥,手写一个简单的虚拟 dom 实现?【JavaScript】
vdom 概念
用JS模拟DOM结构。
DOM变化的对比,放在JS层来做。
提升重绘性能。
比如有abc 三个dom, 如果我们要删除b dom, 以前浏览器的做法是 全部删除abc dom , 然后 在添加b dom 。这样做的成本会非常高。
用JS模拟 dom
例如下面的一个dom 结构:
ini
代码解读
复制代码
<ul id="list">
<li class="item">item1</li>
<li class="item">item2</li>
</ul>
这样的dom 结构,可以模拟为下面的JS :
css
代码解读
复制代码
let dom = {
tag: 'ul',
attrs: {
id: 'list'
},
children: [
{
tag: 'li',
attrs: {className: 'item'},
children: ['item1']
},
{
tag: 'li',
attrs: {className: 'item'},
children: ['item2']
}
]
}
浏览器操作dom 是花销非常大的。执行JS花销要小非常多,所以这就是为什么虚拟dom 出现的一个根本原因。
Vue3.0 实现数据双向绑定的方法是什么?
Vue3.0 通过使用 Composition API 中的 reactive 和 ref 函数来实现数据双向绑定。
- reactive 函数
reactive 函数是 Vue3.0 中用来创建响应式对象的函数。将一个 JavaScript 对象传递给 reactive 函数,它会返回一个新的响应式对象。响应式对象是一个 Proxy 对象,可以在应用程序中使用它来自动追踪数据的变化。
例如,我们可以这样使用 reactive 函数来创建一个响应式对象:
javascript
代码解读
复制代码
import { reactive } from 'vue';
const state = reactive({
message: 'Hello, world!'
});
在上面的示例中,我们使用 reactive 函数创建了一个包含一个 message 属性的响应式对象。
- ref 函数
ref 函数是 Vue3.0 中用来创建一个包含单个值的响应式对象的函数。将一个初始值传递给 ref 函数,它会返回一个新的响应式对象。响应式对象是一个普通对象,它有一个名为 value 的属性,该属性保存了当前值。当 value 属性的值发生改变时,Vue3.0 会自动更新应用程序的界面。
例如,我们可以这样使用 ref 函数来创建一个响应式对象:
import { ref } from 'vue';
const count = ref(0);
在上面的示例中,我们使用 ref 函数创建了一个包含初始值为 0 的响应式对象。
- 双向绑定的实现
Vue3.0 中的双向绑定可以通过在模板中使用 v-model 指令来实现。v-model 指令是 Vue3.0 中用来实现表单元素和组件的双向数据绑定的指令。例如,我们可以这样使用 v-model 指令来实现一个表单输入框的双向绑定:
htmlCopy code<template>
<input v-model="message" />
<p>{{ message }}</p>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const message = ref('');
return {
message
};
}
};
</script>
在上面的示例中,我们在模板中使用 v-model 指令将输入框和 message 响应式对象进行双向绑定。当用户在输入框中输入文本时,message 响应式对象的值会自动更新,当 message 响应式对象的值发生改变时,界面上的文本也会自动更新。
总之,Vue3.0 使用 reactive 和 ref 函数来实现数据双向绑定。使用 reactive 函数可以创建包含多个属性的响应式对象,使用 ref 函数可以创建包含单个值的响应式对象。通过在模板中使用 `v-model
指令可以实现表单元素和组件的双向数据绑定,将表单元素的值绑定到响应式对象的属性上,当响应式对象的属性值变化时,自动更新绑定的表单元素的值。
除了使用 v-model 指令实现双向绑定,Vue3.0 也提供了 watch 函数和 watchEffect 函数来实现响应式数据的监听和副作用函数的执行。这些函数可以用来监听响应式数据的变化,从而执行特定的操作。下面是一个使用 watch 函数监听响应式数据变化的示例:
xml
代码解读
复制代码
htmlCopy code<template>
<div>{{ count }}</div>
<button @click="increment">Increment</button>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`);
});
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
};
</script>
在上面的示例中,我们使用 watch 函数监听 count 响应式对象的变化,当 count 响应式对象的值发生变化时,会自动调用回调函数,打印出 count 变化前和变化后的值。
另外,Vue3.0 中还提供了 computed 函数用来计算一个响应式对象的值,toRefs 函数用来将一个响应式对象转换为普通的对象,并且在 TypeScript 中使用时可以使用 defineComponent 函数来定义组件的类型,从而提高代码的可读性和可维护性。
简单手写下 vue 双向绑定小例子
<div id="app">
<input type="text" :value="message" @input="message = $event.target.value">
<p>{{ message }}</p>
</div>
class Reactive {
constructor(data) {
this._data = data;
this._watchers = new Set();
return new Proxy(data, {
get: (target, key) => {
this._watchers.add(key);
return Reflect.get(target, key);
},
set: (target, key, value) => {
const result = Reflect.set(target, key, value);
this._watchers.forEach(watcher => {
if (this._data.hasOwnProperty(watcher)) {
// 这里可以添加具体的更新逻辑,例如调用某个方法或重新渲染等
console.log(`${watcher} changed to ${value}`); // 模拟更新视图或其他逻辑
}
});
return result;
}
});
}
}
function createApp(data) {
const vm = new Reactive(data);
const app = document.getElementById('app');
app.innerHTML = `
<input type="text" :value="${vm.message}" @input="vm.message = $event.target.value">
<p>${vm.message}</p>
`;
}
createApp({ message: 'Hello Vue!' });