viprespro / javascript-fucking-questions

Collections of questions in JavaScript which may be confused or fucked easily!

Home Page:https://aresuper.cn/javascript-fucking-questions/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JavaScript易错题集列表

💪 🚀 持续更新学习或工作中遇到的问题。

折叠部分查看答案,祝好运 ❤️ 😄!


1. ['1', '2', '3'].map(parseInt)结果是什么?
答案

答案: [1, NaN, NaN]

map方法

map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。

var new_array = arr.map(function callback(currentValue[,index[, array]]) {
 // Return element for new_array
 }[, thisArg])

callback回调函数需要三个参数, 我们通常只使用第一个参数 (其他两个参数是可选的)。 currentValue 是callback 数组中正在处理的当前元素。 index可选, 是callback 数组中正在处理的当前元素的索引。 array可选, 是callback map 方法被调用的数组。 另外还有thisArg可选, 执行 callback 函数时使用的this 值

const arr = [1, 2, 3];
arr.map((num) => num + 1); // [2, 3, 4]

parseInt

parseInt() 是JavaScript的内置函数,解析一个字符串参数,并返回一个指定基数的整数 (数学系统的基础)。

const intValue = parseInt(string[, radix]);

string 要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。

radix 一个介于包含2和36之间的整数(数学系统的基础),表示上述字符串的基数。基数未填或者传0那么将默认为10。 返回值 返回一个整数或NaN

运行流程

['1', '2', '3'].map((item, index) => parseInt(item, index))

// 每次执行
parseInt('1', 0) // 1 
parseInt('2', 1) // NaN 
parseInt('3', 2) // NaN 

如何达到预期效果

['1', '2', '3'].map((item) => parseInt(item))
OR
['1', '2', '3'].map(Number)

parseInt(value,radix)转换规则(伴随radix)总结

  • value若不是字符串,先转为字符串
  • 检查radix是否在区间[2,36]之间,0或不填默认为10,不再此区间直接返回NaN,parseInt('2', 1) 1不在有效值内,返回NaN
  • 依顺序找到字符串value中满足小于radix的数,直到无效数值型,parseInt('3', 2) 2表示为按照二进制解析,只有0 1属于有效数字,3不为有效数字,返回NaN

2. 以下输出结果是什么?
 let i,j,k;
 for( i = 0 , j = 0; i < 10 , j < 6; i++, j++ ) {
   k = i+j;
 }
 console.log('k:', k)
答案

答案: k: 10

解析:考察for 循环以及逗号操作。

逗号操作符 逗号操作符 对它的每个操作对象求值(从左至右),然后返回最后一个操作对象的值。

console.log((1,2)) // 2
console.log((x=2, ++x)) // 3
const a = {
  foo: function() {
    console.log(this === window);
  }
};

a.foo(); // this此时指向a 显然this !== window

// 使用逗号操作符
(0, a.foo)(); // 'true' in console

// 使用逗号操作符之后等价于
const b = a.foo
b()  // 'true' in console

回到题目 for循环中,循环条件判断时,由于逗号操作符的缘故,继续循环的条件为最后一个,流程如下: i=0, j=0 => 0 i=1, j=1 => 2 i=2, j=2 => 4 i=3, j=3 => 6 i=4, j=4 => 8 i=5, j=5 => 10

题目修改

 let i,j,k;
 for( i = 0 , j = 0; i < 6 , j < 10; i++ , j++ ) {
   k = i+j;
 }
 console.log('k:', k) // k: 18

总结 如果j的最终值大于i,同样会以j的作循环条件遍历次数。


3. 以下输出结果?
const obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
console.log(obj)
obj.push(1)
obj.push(2)
console.log(obj)
答案

答案:Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]

// 考察点
// 1. 当对象存在splice属性时 控制台输出会是数组的形式 但obj仍然是对象类型
// 2. push的位置取决于此时length的长度 此时length为2 所以执行push会从小标2开始 2次push覆盖了3、4,length长度变为4

// 存在splice函数
const o = {
  length: 1,
  splice: Array.prototype.splice,
  push: Array.prototype.push
}
o.push(1)
o.push(2)
console.log('o:', o) // [empty, 1, 2, splice: f, push: f]

// 不存在splice函数时当对象处理
const o2 = {
  length: 1,
  push: Array.prototype.push
}
o.push(1)
o.push(2)
console.log('o2:', o2) // {length: 1, push: ƒ}

问题讨论:Advanced-Frontend/Daily-Interview-Question#76


4. 输出以下结果?
// example 1
var a={}, b='123', c=123;  
a[b]='b';
a[c]='c';  
console.log(a[b]); 

// example 2
var a={}, b=Symbol('123'), c=Symbol('123');  
a[b]='b';
a[c]='c';  
console.log(a[b]); 

// example 3
var a={}, b={key:'123'}, c={key:'456'};  
a[b]='b';
a[c]='c';  
console.log(a[b]); 
答案

答案:c b c

解析:此题考察对象的键名的转换

  • 对象的键名只能是字符串和 Symbol 类型

  • 其他类型的键名会被转换成字符串类型

  • 对象转字符串默认会调用 toString 方法

    // example 1
    var a={}, b='123', c=123;
    a[b]='b';
    
    // c 的键名会被转换成字符串'123',这里会把 b 覆盖掉。
    a[c]='c';  
    
    // 输出 c
    console.log(a[b]);
    // example 2
    var a={}, b=Symbol('123'), c=Symbol('123');  
    
    // b 是 Symbol 类型,不需要转换。
    a[b]='b';
    
    // c 是 Symbol 类型,不需要转换。任何一个 Symbol 类型的值都是不相等的,所以不会覆盖掉 b。
    a[c]='c';
    
    // 输出 b
    console.log(a[b])
    // example 3
    var a={}, b={key:'123'}, c={key:'456'};  
    
    // b 不是字符串也不是 Symbol 类型,需要转换成字符串。
    // 对象类型会调用 toString 方法转换成字符串 [object Object]。
    a[b]='b';
    
    // c 不是字符串也不是 Symbol 类型,需要转换成字符串。
    // 对象类型会调用 toString 方法转换成字符串 [object Object]。这里会把 b 覆盖掉。
    a[c]='c';  
    
    // 输出 c
    console.log(a[b]);


5. 编写一个函数实现以下需求?
add(1); // 1
add(1)(2);	// 3
add(1)(2)(3)// 6
add(1)(2, 3); // 6
add(1, 2)(3); // 6
add(1, 2, 3); // 6
答案

考察:函数柯里化

curry 的概念:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数

// 参数固定的情况
const fn = (a, b, c) => a + b + c
const curry = (fn) => {
return function curried(...args) {
  if (args.length < fn.length) {
    return function () {
      return curried(...args.concat(Array.from(arguments)))
    }
  }
  return fn(...args)
}
}
const add = curry(fn)
console.log(add(1, 2)(4))

// 2.确定参数的情况
function add() {
const colls = [...arguments]
const fn = function () {
  const fn_args = [...arguments]
  colls.push(...fn_args)
  return fn
}
fn.toString = function () {
  return colls.reduce((a, b) => a + b)
}
return fn
}


6.以下输出结果是什么?
function Foo(){
  getName = function(){
      console.log(1);
  };
  return this;
} 

Foo.getName = function(){
  console.log(2);
}

Foo.prototype.getName = function(){
  console.log(3);
}

var getName = function(){
  console.log(4);
}

function getName(){
  console.log(5);
}

// Output?
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
答案

答案: 2 4 1 1 2 3 3

分析:考查原型原型链、隐式定义、变量提升等知识点。 Foo.getName() 代码中直接定义,输出2

getName() var 变量定义引起的变量提升,理解以下代码

var getName = function(){
      console.log(4);
  }
function getName(){
  console.log(5);
}

// 等价于
var getName
function getName() {
    console.log(5)
}
getName = function(){
    console.log(4);
}

显然 getName已被覆盖,所以输出4

Foo().getName() 调用Foo方法,函数里面隐式定义了一个getName方法,返回this实例,考虑浏览器环境运行,此时相当于Window.Foo().getName(), this指向window,而隐式定义的变量则相当于window的属性,此时getName也是覆盖了输出为4的getName, 即此时``Foo().getName()`输出1

getName()等价于上面的一个输出 1

new Foo.getName() 即 new (Foo.getName()) 输出2

new Foo().getName() 即(new Foo()).getName(), 获取原型上的getName方法 输出3

new new Foo().getName() 即类似于上面2 输出3


7. 下面的输出是什么?
class Example extends React.Component {
  constructor() {
    super();
    this.state = {
      val: 0
    };
  }

  componentDidMount() {
    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // ?

    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // ?

    setTimeout(() => {
      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // ?

      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // ?
    }, 0);
  }

  render() {
    return null;
  }
};
答案

答案: 0 0 2 3

解析:考察react中setState的原理。

  • 合成事件及生命周期函数setState表现为异步行为,setState将会批处理
  • 原生事件或setTimeout等异步任务中表现为同步行为


8.以下代码输出是什么?(typeof)
function foo() {
  let x = (y = 0);
  x++;
  y++;
  return x;
}

console.log(foo(), typeof x, typeof y);
答案

答案:1, undefined and number

解析:

  1. 首先foo()的调用,x++之后输1
  2. foo函数x,y的定义等价于let x; window.y = 0; x = window.y,由于函数作用域的缘故,全局上下文将不能访问到x,所以typeof x 为undefined
  3. y全局,显然为number


9.以下代码输出是什么?
var y = 1;
if (function f() {}) {
  y += typeof f;
}
console.log(y);
答案

答案:1undefined

解析:

  1. function f(){} 对象类型,总是返回true
  2. 由于function f(){}是在运行时调用,没有声明的地方,所以是undefined,结果显而易见。


10.以下在非严格模式下输出是什么?
function printNumbers(first, second, first) {
  console.log(first, second, first);
}
printNumbers(1, 2, 3);
答案

答案:3,2,3

解析:

  1. 在非严格模式下,常规 JavaScript 函数允许重复的命名参数
  2. 后面参数的值,会覆盖同名参数的值
  3. 严格模式下,重名参数会抛出语法错误


11.以下代码的输出是什么?
console.log(String.prototype.trimLeft.name === "trimLeft");
console.log(String.prototype.trimLeft.name === "trimStart");
答案

答案:false true

解析:由于 web 兼容性的原因,旧的方法名称 'trimLeft' 仍然充当 'trimStart' 的别名。因此,“trimLeft”的原型始终是“trimStart


12.Math.max()
console.log(Math.max());
答案

答案:-Infinity

解析:-Infinity 是初始比较值,因为几乎所有其他值都更大。因此,当没有提供参数时,将返回 -Infinity。注意:无参是有效的情况。


13.以下代码输出是什么?
console.log(10 == [10]);
console.log(10 == [[[[[[[10]]]]]]]);
答案

答案:true true

解析:上面的比较可以转换为10 === Number([10].valueOf().toString()); // 10


14.以下输出是什么?
let numbers = [1, 2, 3, 4, NaN];
console.log(numbers.indexOf(NaN));
答案

答案:-1

解析:indexOf 在内部使用严格相等运算符 (===) 并且 NaN === NaN 评估为假。由于 indexOf 无法在数组中找到 NaN,因此它总是返回 -1。但是可以使用其他方式来判断

let numbers = [1, 2, 3, 4, NaN];
console.log(numbers.findIndex(Number.isNaN)); // 4

console.log(numbers.includes(NaN)); // true


15.以下输出是什么?
var set = new Set();
set.add("+0").add("-0").add(NaN).add(undefined).add(NaN);
console.log(set);
答案

答案:Set(4) {"+0", "-0", NaN, undefined}

解析:

  • 所有的NaN值都是相等的
  • +0与-0被视为不同的值


16.以下输出是什么?
console.log(
  JSON.stringify({ myArray: ["one", undefined, function () {}, Symbol("")] })
);
console.log(
  JSON.stringify({ [Symbol.for("one")]: "one" }, [Symbol.for("one")])
);
答案

答案:{"myArray":['one', null,null,null]}, {}

解析:

  1. undefined、Functions 和 Symbols 不是有效的 JSON 值。因此,这些值要么被省略(在对象中),要么被更改为 null(在数组中)。因此,它返回值数组的空值。
  2. 所有符号键属性将被完全忽略。因此它返回一个空对象({})。


17.以下输出是什么?
const { a: x = 10, b: y = 20 } = { a: 30 };

console.log(x);
console.log(y);
答案

答案:30, 20

解析:

  1. 可以检索对象属性并将其分配给具有不同名称的变量
  2. 当检索到的值未定义时,该属性分配了默认值


18.以下输出是什么?
const obj = { key: "value" };
const array = [...obj];
console.log(array);
答案

答案:TypeError

解析:

  1. 扩展语法只能应用于可迭代对象
  2. 默认情况下,对象是不可迭代的,但是当在数组中使用时,或者与 map()、reduce() 和 assign() 等迭代函数一起使用时,它们变得可迭代。如果你仍然尝试这样做,它仍然会抛出 TypeError: obj is not iterable.


19.以下代码输出是什么?
const myGenerator = (function* () {
  yield 1;
  yield 2;
  yield 3;
})();
for (const value of myGenerator) {
  console.log(value);
  break;
}

for (const value of myGenerator) {
  console.log(value);
}
答案

答案:1

解析:

  1. 一旦迭代器关闭,生成器不应该被重新使用
  2. 生成器已关闭并尝试再次对其进行迭代不会产生更多结果


20.以下代码输出是什么?
const squareObj = new Square(10);
console.log(squareObj.area);

class Square {
  constructor(length) {
    this.length = length;
  }

  get area() {
    return this.length * this.length;
  }

  set area(value) {
    this.area = value;
  }
}
答案

答案:ReferenceError

解析:

  1. 不像函数定义,类的定义不会提升,必须要先定义再引用,否则会出现引用错误的问题


21.以下代码输出是什么?
let msg = "Good morning!!";
msg.name = "John";
console.log(msg.name);
答案

答案:undefined

解析:它在非严格模式返回undefined,在为严格模式返回错误。 在非严格模式下,将创建包装器对象并获取提到的属性。但是在访问下一行的属性后,该对象消失了。


22.以下输出是什么?
let person = { name: 'Lydia' };
const members = [person];
person = null;

console.log(members);
答案

答案:[{ name: "Lydia" }]

解析:变量person指向对象,对象在设置彼此相等时通过引用进行交互,当您将一个变量的引用分配给另一个变量时,您制作了该引用的副本。当person重新赋值为null,不会影响之前的数组的引用。


23.以下输出什么?
function greeting() {
  throw 'Hello world!';
}

function sayHi() {
  try {
    const data = greeting();
    console.log('It worked!', data);
  } catch (e) {
    console.log('Oh no an error:', e);
  }
}

sayHi();
答案

答案:Oh no an error: Hello world!

解析:异常可以是字符串、数字、布尔值或对象。


24.以下输出是什么?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from './counter';

myCounter += 1;

console.log(myCounter);
答案

答案:Error

解析:导入的模块是只读的:您不能修改导入的模块。当我们尝试增加 myCounter 的值时,它会抛出一个错误:myCounter 是只读的,无法修改。


25.以下输出的是什么?
const name = 'Lydia';
age = 21;

console.log(delete name);
console.log(delete age);
答案

答案:false, true

解析:删除操作符返回一个布尔值:成功删除时为 true,否则返回 false。但是,使用 var、const 或 let 关键字声明的变量不能使用 delete 运算符删除。 name由const声明,返回false,但age则是添加到window对象上,作为window对象的一个属性,能删除成功。


26.以下的输出是什么?
const settings = {
  username: 'lydiahallie',
  level: 19,
  health: 90,
};

const data = JSON.stringify(settings, ['level', 'health']);
console.log(data);
答案

答案:"{"level":19, "health":90}"

解析:

  • JSON.stringify 的第二个参数是替换器。替换器可以是一个函数或一个数组,并允许您控制应该对值进行字符串化的内容和方式。
  • 如果替换器是一个数组,那么只有包含在数组中的属性名称会被添加到 JSON 字符串中。
  • 如果替换器是一个函数,则在您要字符串化的对象中的每个属性上都会调用此函数。此函数返回的值将是属性添加到 JSON 字符串时的值。


27.以下输出是什么?
// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));

// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;
答案

答案:running sum.js, running index.js, 3

解析:

  • 使用 import 关键字,所有导入的模块都被预先解析。
  • 这是 CommonJS 中的 require() 和 import 的区别!使用 require(),你可以在代码运行时按需加载依赖。
  • 使用require,你能得到你以为的答案。


28.以下输出是什么?
function foo() {
  return 'Here is pizza!';
}

const bar = () =>
  "Here's chocolate... now go hit the gym already.";

console.log(foo.prototype);
console.log(bar.prototype);
答案

答案:{ constructor: ...} undefined

解析:

  • 普通函数如foo,都存在prototype属性,它是一个拥有constructor属性的一个对象
  • 箭头函数bar,不存在prototype属性的,访问将会得到undefined


29.以下输出是什么?
const info = {
  [Symbol('a')]: 'b',
};

console.log(info);
console.log(Object.keys(info));
答案

答案:{ constructor: ...} undefined

解析:考察symbol作为键值

  • symbol作为键值是不可枚举的,Object.keys将返回[]
  • 打印整个对象时,所有的属性都是可见的,即使是不可枚举的属性


30.以下输出是什么?
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))
答案

答案:{ constructor: ...} undefined

解析:考察展开运算符与箭头函数中返回对象

  • 展开运算符中,对应x=1,y=[2,3,4],所有返回[1,[2,3,4]]
  • 而箭头函数中返回一个对象时,只有一条语句返回,则需要使用括号进行包裹。 即const getUser = user => ({ name: user.name, age: user.age })


31.以下输出是什么?
const name = 'Lydia';

console.log(name());
答案

答案:{ constructor: ...} undefined

解析:TypeError

  • 变量名保存一个字符串的值,它不是一个函数,因此不能调用
  • 当值不是预期的类型时,会抛出 TypeErrors。 JavaScript 期望 name 是一个函数,因为我们试图调用它
  • 当你编写了无效的 JavaScrip 内容时,会抛出 SyntaxErrors
  • 当 JavaScript 无法找到对您尝试访问的值的引用时,会引发 ReferenceErrors


32.以下输出是什么?
const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
};

const colors = ['pink', 'red', 'blue'];

console.log(colorConfig.colors[1]);
答案

答案:TypeError


33.这个方法是的作用是?
JSON.parse();
答案

答案:Parses JSON to a JavaScript value

JSON string to a JavaScript value:
const jsonNumber = JSON.stringify(4); // '4'
JSON.parse(jsonNumber); // 4

const jsonArray = JSON.stringify([1, 2, 3]); // '[1, 2, 3]'
JSON.parse(jsonArray); // [1, 2, 3]

const jsonArray = JSON.stringify({ name: 'Lydia' }); // '{"name":"Lydia"}'
JSON.parse(jsonArray); // { name: 'Lydia' }


34.以下的输出是什么?
let name = 'Lydia';

function getName() {
  console.log(name);
  let name = 'Sarah';
}

getName();
答案

答案:ReferenceError

  • 每个函数都有自己的执行上下文(或作用域),当访问name变量,由于自身存在name变量,但是用let声明,会形成暂时性死区,引发ReferenceError


35.以下输出是什么?
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));
答案

答案:false false true false

  • 使用Number.isNaN方法,你可以检查你传递的值是否为数值并且等于NaN
  • 使用isNaN方法,你可以检查你传递的值是否不是数字


36.以下输出是什么?
const randomValue = 21;

function getInfo() {
  console.log(typeof randomValue);
  const randomValue = 'Lydia Hallie';
}

getInfo();
答案

答案:false false true false

  • 用 const 关键字声明的变量在初始化之前是不可引用的
  • 在未初始化之前引用会报引用错误


37.以下输出是什么?
const person = { name: 'Lydia Hallie' };

Object.seal(person);

person.name = "Evan Bacon"

console.log(person)
答案

答案:{ name: 'Evan Bacon' }

  • 使用 Object.seal,我们可以防止添加新属性或删除现有属性,但是,您仍然可以修改现有属性的值


38.以下输出是什么?
let randomValue = { name: "Lydia" }
randomValue = 23

if (!typeof randomValue === "string") {
	console.log("It's not a string!")
} else {
	console.log("Yay it's a string!")
}
答案

答案:Yay it's a string!

  • !typeof randomValue === "string" 会先计算typeof randomValue 为'number' string,取非之后为false,与string比较总是返回false,所以走else语句


39. 当a为何值时,能打印出xxx?
var a = ?
if (a == 1 && a == 2 && a == 3) {
  console.log('xxx')
}
答案

答案:见下

解析:考察js中的隐式类型转换。

引用类型转换原始值的步骤

  • 先调用对象的Symbol.toPrimitive方法,如果不存在这个
  • 再调用valueOf方法 如果该方法返回一个原始值那么就用此原始值
  • 否则,调用toString方法,返回字符串表示

答案1

const a = {
  value: 1,
  valueOf() {
    return this.value++
  },
 }

答案2

const a = [1,2,3]
a.toString = a.shift


40. 如何实现 x === x + 1?
答案

答案:Number.MAX_SAFE_INTEGER + 1

const x = Number.MAX_SAFE_INTEGER + 1 
console.log(x === x + 1) // true


41. 下面代码输出为?
function foo(a, b = 1, c) {
  console.log(foo.length)
}

foo(1,2,3)
答案

答案:1

解析:函数长度属性及存在默认参数

  • es6引入了默认参数。此前,函数length属性用于返回所有函数参数编号
  • 默认参数的引入,length属性发生了变化,带默认值的参数是可选的,所以这样的参数不计入length中
  • 默认参数后面的参数也是可选,后面的也不会计入长度属性计算中


42. 以下代码输出?
const obj = {};

Object.defineProperty(obj, 'count', {
 value: '100'
});

console.log(obj.count);
delete obj.count;
console.log(obj.count);
答案

答案:100 100

解析:Object.defineProperty 方法及其默认参数

  • 语法格式:Object.defineProperty(obj, prop, descriptors)
  • descriptors属性描述符
    • 数据描述符 (值 可写 可枚举 可配置)默认情况,不可写 不可枚举 不可配置 可配置属性指定是否可以从对象中删除属性,以及将来是否可以更改属性描述符。题目中由于默认为false 将会别忽略,严格模式下 将会报错
    • 访问描述符 (get set方法)


43. 以下代码输出?
function Foo() {
 this.flag = true;
}

const foo = new Foo();
const bar = Object.create(foo);

const clone1 = { ...bar };
const clone2 = Object.assign({}, bar);

console.log(bar.flag, clone1.flag, clone2.flag);
答案

答案:true undefined undefined

解析:Object.create 和 Object.assign 克隆对象

  • 语法:Object.create(proto[,propertiesObject]) 创建一个新对象 并以proto作为原型 propertiesObject对新创建的对象进行初始化
  • admin本身是没有flag属性 访问时找到其原型对象上的属性
  • 通过展开符与Object.assign()克隆会忽略其原型

他们原型为

admin.__proto__ Foo { flag: true },
clone1.__proto__ [Object: null prototype] {},
clone2.__proto__ [Object: null prototype] {}

克隆包含其原型

const clone1 = { __proto__: Object.getPrototypeOf(obj), ...obj };
const clone2 = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);


44. 以下代码输出?
const str = 'string';
const str2 = String('string');

console.log(str instanceof String);
console.log(str2 instanceof String);
答案

答案:false false

解析:字符串函数和 instanceof 运算符

  • instanceof 运算符仅适用于对象
  • 字符串文字'string'是原始的
  • 非构造函数上下文中的字符串调用(不使用 new 关键字调用)返回一个原始字符串


45. 以下代码输出?
var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a.x);
console.log(b.x);
答案

答案:

undefined {n:2}

解析:

  • 连续=号赋值从右到左
  • .号优先级高于=号赋值


About

Collections of questions in JavaScript which may be confused or fucked easily!

https://aresuper.cn/javascript-fucking-questions/


Languages

Language:Shell 100.0%