1. null 和 undefined 的区别
- null 指空值,undefined 指没有值。
- 或者 undefined 指从未赋值,null 指曾赋过值,但是目前没有值。
- null 是一个特殊关键字,不是标识符,不能被将其当作变量来使用和赋值。然而 undefined 却是一个标识符,可以被当作变量来使用和赋值。
2. 数组去重的方法有哪些
1) 使用 Set
const array = [1, 2, 3, 3, 4, 5, 5]
const uniqueArray = [...new Set(array)] // new Set 后是 set 格式,使用 ...扩展符,转为数组形式
console.log('uniqueArray', uniqueArray)
// 注意:如果数组中含有空元素,如:[1, 2, , 3],则空元素会被转为 undefined, 即 [1,2,undefined,3]
2) 使用 filter 和 indexOf
const array = [1, 2, 3, 3, 4, 5, 5, null, null, undefined, 'wew', 'we']
const uniqueArray = array.filter((value, index, self) => {
return self.indexOf(value) === index;
});
console.log(uniqueArray);
3) 使用 reduce
数组的 reduce() 方法是 js 中的一个高阶函数,用于对数组中的每个元素进行累积操作,并最终返回一个结果。
reduce() 方法接受两个参数:回调函数和初始值。回调函数可以接受四个参数:累加器、当前值、当前索引和原始数组。
回调函数在数组的每个元素上执行,并将累加器和当前值作为参数传递进去。它可以执行任何操作,并返回一个新的累加器值。在等次迭代过程中,累加器的值会被更新。
array.reduce(callback, initialValue);
const array = [1, 2, 3, 3, 4, 5, 5, null, null, undefined, 'wew', 'we']
const uniqueArray = array.reduce((accumulator, currentValue) => {
if (!accumulator.includes(currentValue)) {
accumulator.push(currentValue)
}
return accumulator
}, [])
console.log(uniqueArray);
4) 使用 for 循环和 includes
const array = [1, 2, 3, 3, 4, 5, 5, null, null, undefined, 'wew', 'we']
const uniqueArray = []
for(let i = 0; i < array.length; i++) {
if(!uniqueArray.includes(array[i])) {
uniqueArray.push(array[i])
}
}
console.log('--uniqueArray--', uniqueArray);
5)借用临时对象的方式
function unique(arr) {
let newArr = []
let temp = {}
let item;
for(let i = 0, len = arr.length; i < len; i++) {
item = arr[i];
if(!temp[item]) {
temp[item] = true;
newArr.push(item);
}
return newArr;
}
}
3. bind、call、apply 区别
- call 和 apply 都是为了改变 this 的指向。作用都是相同的,只是传参的方式不同。
- 除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组。
let a = {
value: 1
}
function getValue(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
getValue.call(a, 'why', '27')
getValue.apply(a, ['why', '27'])
bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。
4. == 和 === 区别
在 JavaScript 中,== 和 === 是用于比较两个值的运算符。
-
==(相等运算符):
- == 运算符用于比较两个值是否相等。
- 当使用 == 运算符进行比较时,会进行类型转换,使得两个值具有相同的类型,然后再进行比较。
- 如果两个值的类型不同,JavaScript 会尝试将它们转换为相同的类型,然后再进行比较。
- 在进行比较时,会进行隐式类型转换,例如将字符串转换为数字,将布尔值转换为数字等。
- 注意:由于类型转换的规则比较复杂,因此使用 == 运算符时需要小心,以避免意外的结果。
-
===(严格相等运算符):
- === 运算符用于比较两个值是否严格相等。
- 当使用 === 运算符进行比较时,不会进行类型转换。
- 只有当两个值的类型和值都相等时,才会返回 true;否则,返回 false。
- 使用 === 运算符可以确保比较的准确性,并避免类型转换可能引起的问题。
下面是一个示例来说明 == 和 === 的区别:
const num = 5;
const str = "5";
console.log(num == str); // 输出:true,进行了类型转换,比较的是值
console.log(num === str); // 输出:false,不进行类型转换,类型不同
5. 使用关键字new
创建新实例对象经过了哪些步骤
- 在内存中创建新对象。
- 将新对象的
__proto__
指向构造函数的protoType
(原型对象)上。 - 将构造函数的作用域赋值给新对象。(即构造函数的
this
指向新对象) - 执行构造函数内部代码,给新对象添加属性。
- 如果构造函数返回一个非空对象,那么就返回这个对象,否则返回新对象。
6. vue2中,data 为什么是一个函数?
-
vue中组件是用来复用的,为了防止data复用(同一个组件被复用多次会创建多个实例)
-
vue组件中的data数据都应该是相互隔离、互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。
-
当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件示例创建一个私有的数据空间,让各个组件实例维护各自的数据。
-
当我们组件的data单纯的写成对象形式,这些实例用的是同一个构造函数,由于JS的特性所致,所有的组件实例共用了一个data,就会造成全局污染。
7. v-if 和 v-show 区分使用场景
v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不 做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
8. computed 和 watch 区分使用场景
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。