- 下面代码的输出是什么?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from './counter';
myCounter += 1;
console.log(myCounter);
答案:Error
解析:
引入模块是只读的,不能修改。
- 下面代码的输出是什么?
const name = 'Jack';
age = 21;
console.log(delete name);
console.log(delete age);
答案:false, true
解析:
delete
操作符返回一个布尔值,true
表示返回成功,false
为返回失败。但是通过var
,const
,let
关键词声明的变量无法使用delete
操作符删除。
- 下面代码的输出是什么?
const person = { name: 'Jack' };
Object.defineProperty(person, 'age', { value: 21 });
console.log(person);
console.log(Object.keys(person));
答案:{ name: 'Jack', age: '21'}, ['name']
解析:
使用
Object.defineProperty
方法添加的属性默认是不可枚举(not enumerable)。用defineProperty
方法添加的属性默认不可变。你可以通过writable
,configurable
和enumerable
属性来改变这一行为
- 下面代码的输出是什么?
let num = 10;
const increaseNumber = () => num++;
const increasePassedNumber = number => number++;
const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);
console.log(num1);
console.log(num2);
答案:10, 10
解析:
一元操作符
++
先返回 操作值, 再累加 操作值。num1
的值是 10, 因为increaseNumber
函数首先返回num
的值,也就是 10,随后再进行num
的累加。
num2
是10因为我们将num1
传入increasePassedNumber
。形参number
接收的值是10,所以num2
也是10.
- 下面代码的输出是什么?
const value = { number: 10 };
const multiply = (x = {...value}) => {
console.log(x.number *= 2);
}
multiply();
multiply();
multiply(value);
multiply(value);
答案:20, 20, 20, 40
解析:
x = {...value}
这种解构赋值的结果是给x创建了与原对象有相同属性的新对象,产生了新的的内存空间,所以此时对x的属性操作不影响原来的对象。
- 下面代码的输出是什么?
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
答案:1 2, undefined 3, undefined 4
解析:
reduce
传入的参数是函数,那么该函数应该有返回值,如果没有则默认返回undefined
- 下面代码的输出是什么?
// 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
则 running index.js, running sum.js, 3会被依次打印。
- 下面代码的输出是什么?
async function getData() {
return await Promise.resolve('hello world');
}
const data = getData();
console.log(data);
答案:Promise{}
解析:
异步函数始终返回一个
promise
。当我们调用getData()
并将其赋值给data
,此时data
为getData
方法返回的一个挂起的promise
,该promise
并没有解决。如果我们想要访问已解决的值 "hello world",可以在data
上使用.then()
方法:data.then(res=>console.log(res))
这样将打印 "hello world"
- 下面代码的输出是什么?
function addToList(item, list) {
return list.push(item);
}
const result = addToList('apple', ['banana']);
console.log(resule);
答案:2
解析:
push()
方法返回新数组的长度。
- 下面代码的输出是什么?
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
};
myObject.func();
答案:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
解析:
在外部函数中,
this
和self
两者都指向了myObject
,因此两者都可以正确地引用和访问foo
。内部函数为自执行函数,其默认调用者是window
,因此该执行性函数的内部this
指向window
。但是self
是自定义变量,它会通过作用域链逐层向上查找,最后可以找到其在上层作用域中已经有定义。
- 下面代码的输出是什么?
console.log(typeof NaN === 'number');
console.log(NaN === NaN);
答案:true, false
- 下面代码的输出是什么?
for (var i = 0; i < 5; i++) {
setTimeout(function() { console.log(i); }, i * 1000 );
}
答案:5, 5, 5, 5, 5
怎么才能按照预期输出0,1,2,3,4
// 方法1将var改为let
for (let i = 0; i < 5; i++) {
setTimeout(function() { console.log(i); }, i * 1000 );
}
// 方法2 外面封装一层自执行函数,形成私有作用域
for (var i = 0; i < 5; i++) {
(function(x) {
setTimeout(function() { console.log(x); }, x * 1000 );
})(i);
}