Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React

  • Vue

  • JavaScript文章

    • new命令原理
    • ES5面向对象
    • ES6面向对象
    • 多种数组去重性能对比
    • 几个高级的JS API
    • JS随机打乱数组
    • 判断是否为移动端浏览器
    • 防抖与节流函数
    • JS获取和修改url参数
    • 比typeof运算符更准确的类型判断
    • Navigator clipboard介绍使用
    • Javascript 语法错题集
      • ESM和CommonJS详解
      • ColorThief的介绍与使用
      • 三级目录

    • 学习笔记

    • openlayers

    • threejs

    • MapboxGL

    • 工具

    • 源码合集

    • 前端
    • JavaScript文章
    东流
    2024-05-28
    目录

    Javascript 语法错题集

    • 题库来源: JavaScript 进阶问题列表

    # 1. 输出是什么?

    const shape = {
      radius: 10,
      diameter() {
        return this.radius * 2;
      },
      perimeter: () => 2 * Math.PI * this.radius,
    };
    
    shape.diameter();
    shape.perimeter();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    • A: 20 and 62.83185307179586
    • B: 20 and NaN
    • C: 20 and 63
    • D: NaN and 63
    答案

    答案:B

    注意 diameter 的值是一个常规函数,但是 perimeter 的值是一个箭头函数。

    对于箭头函数,this 关键字指向的是它当前周围作用域(简单来说是包含箭头函数的常规函数,如果没有常规函数的话就是全局对象),这个行为和常规函数不同。这意味着当我们调用 perimeter 时,this 不是指向 shape 对象,而是它的周围作用域(在例子中是 window)。

    在 window 中没有 radius 这个属性,因此返回 undefined。


    # 2.所有对象都有原型

    • A:对
    • B:错
    答案

    答案:B 除了基本对象(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如 .toString。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。


    # 3.输出是什么?

    [1, 2, 3].map((num) => {
      if (typeof num === "number") return;
      return num * 2;
    });
    
    1
    2
    3
    4
    • A:[]
    • B:[null,null,null]
    • C:[undefined,undefined,undefined]
    • D: [3 x empty]
    答案

    对数组进行映射的时候,num就是当前循环到的元素。在这个例子中,所有的映射都是 number 类型,所以 if 中的判断typeof num === "number"结果都是true.map 函数创建了新数组并且将函数的返回值插入数组。

    但是,没有任何值返回。当函数没有返回任何值时,即默认返回 undefined.对数组中的每一个元素来说,函数块都得到了这个返回值,所以结果中每一个元素都是 undefined.


    # 4. 输出什么?

    const name = "Lydia Hallie";
    console.log(name.padStart(13));
    console.log(name.padStart(2));
    
    1
    2
    3
    • A: "Lydia Hallie", "Lydia Hallie"
    • B: " Lydia Hallie", " Lydia Hallie" ("[13x whitespace]Lydia Hallie", "[2x whitespace]Lydia Hallie")
    • C: " Lydia Hallie", "Lydia Hallie" ("[1x whitespace]Lydia Hallie", "Lydia Hallie")
    • D: "Lydia Hallie", "Lyd"
    答案

    答案:C

    使用padStart方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串Lydia Hallie的长度为12,因此name.padStart(13)在字符串的开头只会插入 1(13 - 12 = 1)个空格。

    如果传递给padStart方法的参数小于字符串的长度,则不会添加填充。


    # 5. 输出什么?

    async function getData() {
      return await Promise.resolve("I made it!");
    }
    
    const data = getData();
    console.log(data);
    
    1
    2
    3
    4
    5
    6
    • A: "I made it!"
    • B: Promise {<resolved>: "I made it!"}
    • C: Promise {<pending>}
    • D: undefined
    答案

    答案:C

    异步函数始终返回一个 promise。await仍然需要等待 promise 的解决:当我们调用getData()并将其赋值给data,此时data为getData方法返回的一个挂起的 promise,该 promise 并没有解决。

    如果我们想要访问已解决的值"I made it!",可以在data上使用.then()方法:

    data.then(res => console.log(res))

    这样将打印 "I made it!"


    # 6. 输出什么?

    const box = { x: 10, y: 20 };
    
    Object.freeze(box);
    
    const shape = box;
    shape.x = 100;
    console.log(shape);
    
    1
    2
    3
    4
    5
    6
    7
    • A: { x: 100, y: 20 }
    • B: { x: 10, y: 20 }
    • C: { x: 100 }
    • D: ReferenceError
    答案

    答案:B

    Object.freeze使得无法添加、删除或修改对象的属性(除非属性的值是另一个对象)。

    当我们创建变量shape并将其设置为等于冻结对象box时,shape指向的也是冻结对象。你可以使用Object.isFrozen检查一个对象是否被冻结,上述情况,Object.isFrozen(shape)将返回true。

    由于shape被冻结,并且x的值不是对象,所以我们不能修改属性x。x仍然等于10,{x:10,y:20}被打印。

    注意,上述例子我们对属性x进行修改,可能会导致抛出 TypeError 异常(最常见但不仅限于严格模式下时)。


    # 7. 输出什么?

    const { name: myName } = { name: "Lydia" };
    
    console.log(name);
    
    1
    2
    3
    • A: "Lydia"
    • B: "myName"
    • C: undefined
    • D: ReferenceError
    答案

    答案:D

    当我们从右侧的对象解构属性name时,我们将其值Lydia分配给名为myName的变量。

    使用{name:myName},我们是在告诉 JavaScript 我们要创建一个名为myName的新变量,并且其值是右侧对象的name属性的值。

    当我们尝试打印name,一个未定义的变量时,就会引发ReferenceError。


    # 8. 输出什么?

    var status = "😎";
    
    setTimeout(() => {
      const status = "😍";
    
      const data = {
        status: "🥑",
        getStatus() {
          return this.status;
        },
      };
    
      console.log(data.getStatus());
      console.log(data.getStatus.call(this));
    }, 0);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    • A: "🥑" and "😍"
    • B: "🥑" and "😎"
    • C: "😍" and "😎"
    • D: "😎" and "😎"
    答案

    答案:B

    this关键字的指向取决于使用它的位置。在函数中,比如getStatus,this指向的是调用它的对象,上述例子中data对象调用了getStatus,因此this指向的就是data对象。当我们打印this.status时,data对象的status属性被打印,即"🥑"。

    使用call方法,可以更改this指向的对象。data.getStatus.call(this)是将this的指向由data对象更改为全局对象。在全局对象上,有一个名为status的变量,其值为”😎“。因此打印this.status时,会打印“😎”。


    # 9. 输出什么?

    const person = {
      name: "Lydia",
      age: 21,
    };
    
    for (const [x, y] of Object.entries(person)) {
      console.log(x, y);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    • A: name Lydia and age 21
    • B: ["name", "Lydia"] and ["age", 21]
    • C: ["name", "age"] and undefined
    • D: Error
    答案

    答案:A Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,上述情况返回一个二维数组,数组每个元素是一个包含键和值的数组:

    [['name','Lydia'],['age', 21]]

    使用for-of循环,我们可以迭代数组中的每个元素,上述情况是子数组。我们可以使用const [x,y]在for-of循环中解构子数组。x等于子数组中的第一个元素,y等于子数组中的第二个元素。

    第一个子阵列是[“name”,“Lydia”],其中x等于name,而y等于Lydia。 第二个子阵列是[“age”,21],其中x等于age,而y等于21。


    # 10. 输出什么?

    const getList = ([x, ...y]) => [x, y]
    const getUser = user => { name: user.name, age: user.age }
    
    const list = [1, 2, 3, 4]
    const user = { name: "Lydia", age: 21 }
    
    console.log(getList(list))
    console.log(getUser(user))
    
    1
    2
    3
    4
    5
    6
    7
    8
    • A: [1, [2, 3, 4]] and SyntaxError
    • B: [1, [2, 3, 4]] and { name: "Lydia", age: 21 }
    • C: [1, 2, 3, 4] and { name: "Lydia", age: 21 }
    • D: Error and { name: "Lydia", age: 21 }
    答案

    答案:A

    getList函数接受一个数组作为其参数。在getList函数的括号之间,我们立即解构这个数组。您可以将其视为:

    [x, ...y] = [1, 2, 3, 4]

    使用剩余的参数... y,我们将所有剩余参数放在一个数组中。在这种情况下,其余的参数是2,3和4。 y的值是一个数组,包含所有其余参数。在这种情况下,x的值等于1,所以当我们打印[x,y]时,会打印[1,[2,3,4]]。

    getUser函数接受一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须将它写在圆括号之间,否则两个花括号之间的所有内容都将被解释为一个块语句!在这种情况下,花括号之间的代码不是有效的 JavaScript 代码,因此会抛出 SyntaxError。

    以下函数将返回一个对象:

    const getUser = user => ({ name: user.name, age: user.age })


    # 11. 输出什么?

    const name = "Lydia";
    
    console.log(name());
    
    1
    2
    3
    • A: SyntaxError
    • B: ReferenceError
    • C: TypeError
    • D: undefined
    答案

    答案:C

    变量name保存字符串的值,该字符串不是函数,因此无法调用。

    当值不是预期类型时,会抛出TypeErrors。JavaScript 期望name是一个函数,因为我们试图调用它。但它是一个字符串,因此抛出TypeError:name is not a function

    当你编写了一些非有效的 JavaScript 时,会抛出语法错误,例如当你把return这个词写成retrun时。 当 JavaScript 无法找到您尝试访问的值的引用时,抛出ReferenceErrors。


    # 12.输出什么?

    const one = false || {} || null;
    const two = null || false || "";
    const three = [] || 0 || true;
    
    console.log(one, two, three);
    
    1
    2
    3
    4
    5
    • A: false null []
    • B: null "" true
    • C: {} "" []
    • D: null null true
    答案

    答案:C

    使用||运算符,我们可以返回第一个真值。如果所有值都是假值,则返回最后一个值。

    (false || {} || null):空对象{}是一个真值。这是第一个(也是唯一的)真值,它将被返回。one等于{}。

    (null || false ||“”):所有值都是假值。这意味着返回传递的值""。two等于""。

    ([] || 0 ||“”):空数组[]是一个真值。这是第一个返回的真值。three等于[]。


    # 13. 输出什么?

    function* generatorOne() {
      yield ["a", "b", "c"];
    }
    
    function* generatorTwo() {
      yield* ["a", "b", "c"];
    }
    
    const one = generatorOne();
    const two = generatorTwo();
    
    console.log(one.next().value);
    console.log(two.next().value);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    • A: a and a
    • B: a and undefined
    • C: ['a', 'b', 'c'] and a
    • D: a and ['a', 'b', 'c']
    答案

    答案:C

    通过 yield 关键字,我们在 Generator 函数里执行yield表达式。通过 yield* 关键字,我们可以在一个Generator 函数里面执行(yield表达式)另一个 Generator 函数,或可遍历的对象 (如数组).

    在函数 generatorOne 中,我们通过 yield 关键字 yield 了一个完整的数组 ['a', 'b', 'c']。函数one通过next方法返回的对象的value 属性的值 (one.next().value) 等价于数组 ['a', 'b', 'c'].

    console.log(one.next().value); // ['a', 'b', 'c']
    console.log(one.next().value); // undefined
    
    1
    2

    在函数 generatorTwo 中,我们使用 yield* 关键字。就相当于函数two第一个yield的值,等价于在迭代器中第一个 yield 的值。数组['a', 'b', 'c']就是这个迭代器。第一个 yield 的值就是 a,所以我们第一次调用 two.next().value时,就返回a。

    console.log(two.next().value); // 'a'
    console.log(two.next().value); // 'b'
    console.log(two.next().value); // 'c'
    console.log(two.next().value); // undefined
    
    1
    2
    3
    4


    # 14. 将会发生什么?

    let config = {
      alert: setInterval(() => {
        console.log("Alert!");
      }, 1000),
    };
    
    config = null;
    
    1
    2
    3
    4
    5
    6
    7
    • A: setInterval 的回调不会被调用
    • B: setInterval 的回调被调用一次
    • C: setInterval 的回调仍然会被每秒钟调用
    • D: 我们从没调用过 config.alert(), config 为 null
    答案

    答案:C

    一般情况下当我们将对象赋值为 null,那些对象会被进行 垃圾回收(garbage collected) 因为已经没有对这些对象的引用了。然而,setInterval的参数是一个箭头函数(所以上下文绑定到对象 config 了),回调函数仍然保留着对 config的引用。只要存在引用,对象就不会被垃圾回收。因为没有被垃圾回收,setInterval 的回调每 1000ms (1s) 会被调用一次。


    # 15. 输出什么?

    const name = "Lydia Hallie";
    
    console.log(!typeof name === "object");
    console.log(!typeof name === "string");
    
    1
    2
    3
    4
    • A: false true
    • B: true false
    • C: false false
    • D: true true
    答案

    答案:C

    typeof name 返回 "string"。字符串 "string" 是一个 truthy 的值,因此 !typeof name 返回一个布尔值 false。false === "object" 和 false === "string" 都返回 false。

    (如果我们想检测一个值的类型,我们应该用 !== 而不是 !typeof)


    # 16. 输出什么?

    const myFunc = ({ x, y, z }) => {
      console.log(x, y, z);
    };
    
    myFunc(1, 2, 3);
    
    1
    2
    3
    4
    5
    • A: 1 2 3
    • B: {1: 1} {2: 2} {3: 3}
    • C: { 1: undefined } undefined undefined
    • D: undefined undefined undefined
    答案

    答案:D

    myFunc 期望接受一个包含 x, y 和 z 属性的对象作为它的参数。因为我们仅仅传递三个单独的数字值 (1, 2, 3) 而不是一个含有 x, y 和 z 属性的对象 ({x: 1, y: 2, z: 3}),x, y 和 z 有着各自的默认值 undefined.


    # 17. 输出什么?

    const name = "Lydia Hallie";
    const age = 21;
    
    console.log(Number.isNaN(name));
    console.log(Number.isNaN(age));
    
    console.log(isNaN(name));
    console.log(isNaN(age));
    
    1
    2
    3
    4
    5
    6
    7
    8
    • A: true false true false
    • B: true false false false
    • C: false false true false
    • D: false true false true
    答案

    答案:C

    通过方法 Number.isNaN,你可以检测你传递的值是否为 数字值 并且是否等价于 NaN。name 不是一个数字值,因此 Number.isNaN(name) 返回 false。age 是一个数字值,但它不等价于 NaN,因此 Number.isNaN(age) 返回 false.

    通过方法 isNaN,你可以检测你传递的值是否一个 number。name 不是一个 number,因此 isNaN(name) 返回 true. age 是一个 number 因此 isNaN(age) 返回 false.


    # 18. 以下哪一项会对对象 person 有副作用?

    const person = { name: "Lydia Hallie" };
    
    Object.seal(person);
    
    1
    2
    3
    • A: person.name = "Evan Bacon"
    • B: person.age = 21
    • C: delete person.name
    • D: Object.assign(person, { age: 21 })
    答案

    答案:A

    使用 Object.seal 我们可以防止新属性 被添加,或者存在属性 被移除.

    然而,你仍然可以对存在属性进行更改。


    # 19. 输出什么?

    class Bird {
      constructor() {
        console.log("I'm a bird. 🦢");
      }
    }
    
    class Flamingo extends Bird {
      constructor() {
        console.log("I'm pink. 🌸");
        super();
      }
    }
    
    const pet = new Flamingo();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    • A: I'm pink. 🌸
    • B: I'm pink. 🌸 I'm a bird. 🦢
    • C: I'm a bird. 🦢 I'm pink. 🌸
    • D: Nothing, we didn't call any method
    答案

    答案:B

    我们创建了类 Flamingo 的实例 pet。当我们实例化这个实例,Flamingo 中的 constructor 被调用。首相,输出 "I'm pink. 🌸",之后我们调用super()。super() 调用父类的构造函数,Bird。Bird 的构造函数被调用,并输出 "I'm a bird. 🦢"。


    # 20. 哪一个选项会导致报错?

    const emojis = ["🎄", "🎅🏼", "🎁", "⭐"];
    
    /* 1 */ emojis.push("🦌");
    /* 2 */ emojis.splice(0, 2);
    /* 3 */ emojis = [...emojis, "🥂"];
    /* 4 */ emojis.length = 0;
    
    1
    2
    3
    4
    5
    6
    • A: 1
    • B: 1 and 2
    • C: 3 and 4
    • D: 3
    答案

    答案:D

    const 关键字意味着我们不能 重定义 变量中的值,它 仅可读。然而,值本身不可修改。数组 emojis 中的值可被修改,如 push 新的值,拼接,又或者将数组的长度设置为 0。


    # 21. 输出什么?

    const createMember = ({ email, address = {} }) => {
      const validEmail = /.+\@.+\..+/.test(email);
      if (!validEmail) throw new Error("Valid email pls");
    
      return {
        email,
        address: address ? address : null,
      };
    };
    
    const member = createMember({ email: "my@email.com" });
    console.log(member);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    • A: { email: "my@email.com", address: null }
    • B: { email: "my@email.com" }
    • C: { email: "my@email.com", address: {} }
    • D: { email: "my@email.com", address: undefined }
    答案

    答案:C

    address 的默认值是一个空对象 {}。当我们设置 member 变量为 createMember 函数返回的对象,我们没有为 address 参数传值,意味着 address 的值为默认的空对象 {}。一个空对象是一个 truthy 值,意味着 address ? address : null 条件会返回 true。address 的值为空对象 {}。


    # 22. 输出什么?

    const user = {
      email: "my@email.com",
      updateEmail: (email) => {
        this.email = email;
      },
    };
    
    user.updateEmail("new@email.com");
    console.log(user.email);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    • A: my@email.com
    • B: new@email.com
    • C: undefined
    • D: ReferenceError
    答案

    答案:A

    updateEmail 函数是一个箭头函数,它没有和 user 对象绑定。这就意味着 this 关键字不会引用到 user 对象,但是会引用到全局对象。user 对象内部的 email 的值不会更新。当打印 user.email 的时候,原始值 my@email.com 被返回。


    编辑 (opens new window)
    #笔记
    上次更新: 2024/12/03, 14:43:37
    Navigator clipboard介绍使用
    ESM和CommonJS详解

    ← Navigator clipboard介绍使用 ESM和CommonJS详解→

    最近更新
    01
    GeoJSON
    05-08
    02
    Circle
    04-15
    03
    CircleMarker
    04-15
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式