# 前端 75 题

back

# 52. 展开(spread )运算符和 剩余(Rest) 运算符有什么区别

剩余元素和展开元素相反,展开元素会“展开”数组变成多个元素,剩余元素会收集多个元素和“压缩”成一个单一的元素

function add(...rest) {
  return rest.reduce((total, current) => total + current);
}
console.log(add(1, 2)); // 3console.log(add(1, 2, 3, 4, 5)); // 15
1
2
3
4

在本例中,我们有一个 add 函数,它接受任意数量的参数,并将它们全部相加,然后返回总数。

const [first, ...others] = [1, 2, 3, 4, 5];
console.log(first); // 1console.log(others); // [2,3,4,5]
1
2

这里,我们使用剩余操作符提取所有剩余的数组值,并将它们放入除第一项之外的其他数组中。

# 54. 什么是包装对象(wrapper object)

引用类型有方法和属性,但是基本类型是没有的

let name = "marko";
console.log(typeof name); // "string"console.log(name.toUpperCase()); // "MARKO"
1
2

name 类型是 string,属于基本类型,所以它没有属性和方法,但是在这个例子中,我们调用了一个 toUpperCase()方法,它不会抛出错误,还返回了对象的变量值。

原因是基本类型的值被临时转换或强制转换为对象,因此 name 变量的行为类似于对象。除 null 和 undefined 之外的每个基本类型都有自己包装对象。也就是:String,Number,Boolean,Symbol 和 BigInt。在这种情况下,name.toUpperCase()在幕后看起来如下:

console.log(new String(name).toUpperCase()); // "MARKO"
1

在完成访问属性或调用方法之后,新创建的对象将立即被丢弃。

# 56. 什么是 NaN?以及如何检查值是否为 NaN

WARNING

NaN是唯一的值,它不等于自己。

function checkIfNaN(value) {
  return value !== value;
}
1
2
3

# 59. 如何检查对象中是否存在某个属性

# 第一种使用 in 操作符号

const o = { prop: "bwahahah", prop2: "hweasa" };
console.log("prop" in o); // trueconsole.log("prop1" in o); // false
1
2

# 第二种使用 hasOwnProperty 方法

hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。

console.log(o.hasOwnProperty("prop2")); // trueconsole.log(o.hasOwnProperty("prop1")); // false
1

# 第三种使用括号符号 obj["prop"]

如果属性存在,它将返回该属性的值,否则将返回 undefined。

console.log(o["prop"]); // "bwahahah"console.log(o["prop1"]); // undefined
1

# 63. in 运算符和 Object.hasOwnProperty 方法有什么区别

# hasOwnPropert 方法

hasOwnPropert()方法返回值是一个布尔值,指示对象自身属性中是否具有指定的属性,因此这个方法会忽略掉那些从原型链上继承到的属性。

Object.prototype.phone= '15345025546';let obj = {  name: '前端小智',  age: '28'}console.log(obj.hasOwnProperty('phone')) // falseconsole.log(obj.hasOwnProperty('name')) // true
1

可以看到,如果在函数原型上定义一个变量 phone,hasOwnProperty 方法会直接忽略掉。

# in 运算符

如果指定的属性在指定的对象或其原型链中,则 in 运算符返回 true。

console.log("phone" in obj); // true
1

可以看到 in 运算符会检查它或者其原型链是否包含具有指定名称的属性。

# 62. Object.seal 和 Object.freeze 方法之间有什么区别

# Object.freeze()

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

# Object.seal()

Object.seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。

# 方法的相同点

  • ES5 新增。
  • 对象不可能扩展,也就是不能再添加新的属性或者方法。
  • 对象已有属性不允许被删除。
  • 对象属性特性不可以重新配置。

# 方法不同点

  • Object.seal 方法生成的密封对象,如果属性是可写的,那么可以修改属性值。
  • Object.freeze 方法生成的冻结对象,属性都是不可写的,也就是属性值无法更改。

# 66. 调用函数,可以使用哪些方法

在 JS 中有 4 种方法可以调用函数。

# 作为函数调用

如果一个函数没有作为方法、构造函数、apply、call 调用时,此时 this 指向的是 window 对象(非严格模式)

//Global
Scopefunction add(a,b){
    console.log(this);
    return a + b;
    }
    add(1,5); // 打印 "window" 对象和 6
    const o = {
        method(callback){
            callback();
            }}
            o.method(function (){
                console.log(this); // 打印 "window" 对象
                });
1
2
3
4
5
6
7
8
9
10
11
12
13

# 作为方法调用

如果一个对象的属性有一个函数的值,我们就称它为方法。调用该方法时,该方法的 this 值指向该对象。

const details = { name : "Marko", getName(){ return this.name; }}details.getName(); // Marko
1

# 作为构造函数的调用

如果在函数之前使用 new 关键字调用了函数,则该函数称为构造函数。构造函数里面会默认创建一个空对象,并将 this 指向该对象。

function Employee(name, position, yearHired) {
  // 创建一个空对象 {}
  // 然后将空对象分配给“this”关键字 //
  this = {};
  this.name = name;
  this.position = position;
  this.yearHired = yearHired; // 如果没有指定 return ,这里会默认返回 this
}
const emp = new Employee("Marko Polo", "Software Developer", 2017);
1
2
3
4
5
6
7
8
9

# 使用 apply 和 call 方法调用

如果我们想显式地指定一个函数的 this 值,我们可以使用这些方法,这些方法对所有函数都可用。

const obj1 = { result: 0 };
const obj2 = { result: 0 };
function reduceAdd() {
  let result = 0;
  for (let i = 0, len = arguments.length; i < len; i++) {
    result += arguments[i];
  }
  this.result = result;
}
reduceAdd.apply(obj1, [1, 2, 3, 4, 5]); // reduceAdd 函数中的 this 对象将是 obj1    
reduceAdd.call(obj2, 1, 2, 3, 4, 5); // reduceAdd 函数中的 this 对象将是 obj2
1
2
3
4
5
6
7
8
9
10
11

# 71. 什么时候不使用箭头函数? 说出三个或更多的例子

  • 当想要函数被提升时(箭头函数是匿名的)
  • 要在函数中使用this/arguments时,由于箭头函数本身不具有this/arguments,因此它们取决于外部上下文
  • 使用命名函数(箭头函数是匿名的)
  • 使用函数作为构造函数时(箭头函数没有构造函数)
  • 当想在对象字面是以将函数作为属性添加并在其中使用对象时,因为咱们无法访问 this 即对象本身。