1. 下面代码的输出是什么?
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
A: Lydia 和 undefined
B: Lydia 和 ReferenceError
C: ReferenceError 和 21
D: undefined 和 ReferenceError
答案 D
let也存在变量提升,但是它存在一个“暂时死区”,在变量未初始化或赋值前不允许访问。
变量的赋值可以分为三个阶段:
- 创建变量,在内存中开辟空间
- 初始化变量,将变量初始化为undefined
- 真正赋值
关于let、var和function:
- let 的「创建」过程被提升了,但是初始化没有提升。
- var 的「创建」和「初始化」都被提升了。
- function 的「创建」「初始化」和「赋值」都被提升了。
2. 下面代码的输出是什么?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
A: 0 1 2 and 0 1 2
B: 0 1 2 and 3 3 3
C: 3 3 3 and 0 1 2
答案:c
由于JavaScript
中的事件执行机制,setTimeout
函数真正被执行时,循环已经走完。 由于第一个循环中的变量i
是使用var
关键字声明的,因此该值是全局的。 在循环期间,我们每次使用一元运算符++
都会将i的值增加1
。 因此在第一个例子中,当调用setTimeout
函数时,i
已经被赋值为3
。
在第二个循环中,使用let
关键字声明变量i:使用let,const
关键字声明的变量是具有块作用域的(块是{}
之间的任何东西)。 在每次迭代期间,i
将被创建为一个新值,并且每个值都会存在于循环内的块级作用域。
3. 下面代码的输出是什么?
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter()
A: 20 and 62.83185307179586
B: 20 and NaN
C: 20 and 63
D: NaN and 63
答案: B
请注意,diameter
是普通函数,而perimeter
是箭头函数。
对于箭头函数,this
关键字指向是它所在上下文(定义时的位置)的环境,与普通函数不同! 这意味着当我们调用perimeter时,它不是指向shape
对象,而是指其定义时的环境(window
)。没有值radius
属性,返回undefined
。
4. 下面代码的输出是什么?
+true;
!"Lydia";
A: 1 and false
B: false and NaN
C: false and false
答案: A
一元加号会尝试将boolean
类型转换为数字类型。 true
被转换为1
,false
被转换为0
。
字符串'Lydia'
是一个真值。 我们实际上要问的是“这个真值是假的吗?”。 这会返回false
。
5. 哪个选项是不正确的?
const bird = {
size: "small"
};
const mouse = {
name: "Mickey",
small: true
};
A: mouse.bird.size
B: mouse[bird.size]
C: mouse[bird["size"]]
D: All of them are valid
答案: A
在JavaScript
中,所有对象键都是字符串(除了Symbol
)。尽管有时我们可能不会给定字符串类型,但它们总是被转换为字符串。
6. 下面代码的输出是什么?
let c = { greeting: "Hey!" };
let d;
d = c;
c.greeting = "Hello";
console.log(d.greeting);
A: Hello
B: undefined
C: ReferenceError
D: TypeError
答案:A
7. 下面代码的输出是什么?
let a = 3;
let b = new Number(3);
let c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
A: true false true
B: false false true
C: true false false
D: false true true
答案:C
new Number()
是一个内置的函数构造函数。 虽然它看起来像一个数字,但它并不是一个真正的数字:它有一堆额外的功能,是一个对象。
当我们使用==
运算符时,它只检查它是否具有相同的值。 他们都有3
的值,所以它返回true
。
==会引发隐式类型转换,右侧的对象类型会自动拆箱为Number类型。
然而,当我们使用===
操作符时,类型和值都需要相等,new Number()
不是一个数字,是一个对象类型。两者都返回 false
。
8. 下面代码的输出是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor;
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor;
}
}
const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
A: orange
B: purple
C: green
D: TypeError
答案: D
colorChange
方法是静态的。 静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。 由于freddie
是一个子级对象,函数不会传递,所以在freddie
实例上不存在colorChange
方法:抛出TypeError。
9. 下面代码的输出是什么?
let greeting;
greetign = {};//Typo!
console.log(greetign);
A: {}
B: ReferenceError: greetign is not defined
C: undefined
答案: A
10. 当我们这样做时会发生什么?
function bark() {
console.log("Woof!");
}
bark.animal = "dog";
A: Nothing, this is totally fine!
B: SyntaxError. You cannot add properties to a function this way.
C: undefined
D: ReferenceError
答案:A
11. 下面代码的输出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = () => this.firstName + this.lastName;
console.log(member.getFullName());
A: TypeError
B: SyntaxError
C: Lydia Hallie
D: undefined undefined
答案:A
不能像使用常规对象那样向构造函数添加属性。 如果要一次向所有对象添加功能,则必须使用原型。 所以在这种情况下应该这样写:
Person.prototype.getFullName = function () {
return `${this.firstName} ${this.lastName}`;
}
这样会使member.getFullName()
是可用的,为什么样做是对的? 假设我们将此方法添加到构造函数本身。 也许不是每个Person实例都需要这种方法。这会浪费大量内存空间,因为它们仍然具有该属性,这占用了每个实例的内存空间。 相反,如果我们只将它添加到原型中,我们只需将它放在内存中的一个位置,但它们都可以访问它!
12. 下面代码的输出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);
A: Person {firstName: "Lydia", lastName: "Hallie"} and undefined
B: Person {firstName: "Lydia", lastName: "Hallie"} and Person {firstName: "Sarah", lastName: "Smith"}
C: Person {firstName: "Lydia", lastName: "Hallie"} and {}
D: Person {firstName: "Lydia", lastName: "Hallie"} and ReferenceError
答案: A
对于sarah
,我们没有使用new
关键字。 使用new
时,它指的是我们创建的新空对象。 但是,如果你不添加new
它指的是全局对象!
我们指定了this.firstName
等于Sarah
和this.lastName
等于Smith
。 我们实际做的是定义global.firstName ='Sarah'
和global.lastName ='Smith
。 sarah'
本身的返回值是undefined
。
事件传播的三个阶段是什么??
A: 目标 > 捕获 > 冒泡
B: 冒泡 > 目标 > 捕获
C: 目标 > 冒泡 > 捕获
D: 捕获 > 目标 > 冒泡
答案:D
在捕获阶段,事件通过父元素向下传递到目标元素。 然后它到达目标元素,冒泡开始。
[图片上传失败...(image-4c8216-1594950692332)]
13. 所有对象都有原型.
A: 对
B: 错误
答案 B
除基础对象外,所有对象都有原型。 基础对象可以访问某些方法和属性,例如.toString
。 这就是可以使用内置JavaScript
方法的原因! 所有这些方法都可以在原型上找到。 虽然JavaScript无法直接在对象上找到它,但它会沿着原型链向下寻找并在那里找到它,这使可以访问它。
基础对象指原型链终点的对象。基础对象的原型是
null
。
14. 下面代码的输出是什么?
function sum(a, b) {
return a + b;
}
sum(1, "2");
A: NaN
B: TypeError
C: "12"
D: 3
答案: C
JavaScript
是一种动态类型语言:我们没有指定某些变量的类型。 在不知情的情况下,值可以自动转换为另一种类型,称为隐式类型转换。 强制从一种类型转换为另一种类型。 在此示例中,JavaScript
将数字1
转换为字符串,以使函数有意义并返回值。 在让数字类型(1
)和字符串类型('2')
相加时,该数字被视为字符串。 我们可以连接像"Hello"+"World"
这样的字符串,所以这里发生的是 "1"+"2"
返回 "12"
。
15. 下面代码的输出是什么?
let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
A: 1 1 2
B: 1 2 2
C: 0 2 2
D: 0 1 2
答案: C
16. 下面代码的输出是什么?
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
A: Lydia 21 ["", "is", "years old"]
B: ["", "is", "years old"] Lydia 21
C: Lydia ["", "is", "years old"] 21
答案: B
如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!
17. 下面代码的输出是什么?
function checkAge(data) {
if (data === { age: 18 }) {
console.log("You are an adult!");
} else if (data == { age: 18 }) {
console.log("You are still an adult.");
} else {
console.log(`Hmm.. You don't have an age I guess`);
}
}
checkAge({ age: 18 });
A: You are an adult!
B: You are still an adult.
C: Hmm.. You don't have an age I guess
答案: C
在比较相等性,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。JavaScript检查对象是否具有对内存中相同位置的引用。 我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。 这就是为什么 { age: 18 } === { age: 18 }
和 { age: 18 } == { age: 18 }
返回 false
的原因。
18. 下面代码的输出是什么?
function getAge(...args) {
console.log(typeof args);
}
getAge(21);
A: "number"
B: "array"
C: "object"
D: "NaN"
答案: C
扩展运算符 (... args)
返回一个带参数的数组。 数组是一个对象,因此 typeof args
返回 object
。
20. 下面代码的输出是什么?
function getAge() {
"use strict";
age = 21;
console.log(age);
}
getAge();
A: 21
B: undefined
C: ReferenceError
D: TypeError
答案: C
使用use strict
,可以确保不会意外地声明全局变量。 我们从未声明变量age
,因为我们使用use strict
,它会引发一个ReferenceError
。 如果我们不使用use strict
,它就会起作用,因为属性age
会被添加到全局对象中。
21. 下面代码的输出是什么?
const sum = eval("10*10+5");
A: 105
B: "105"
C: TypeError
D: "10*10+
答案: A
eval
会为字符串传递的代码求值。 如果它是一个表达式,就像在这种情况下一样,它会计算表达式。 表达式为10 * 10 + 5
计算得到105
。
22. cool_secret可以访问多长时间?
sessionStorage.setItem("cool_secret", 123);
A:永远,数据不会丢失。
B:用户关闭选项卡时。
C:当用户关闭整个浏览器时,不仅是选项卡。
D:用户关闭计算机时。
答案: B
关闭选项卡后,将删除存储在sessionStorage
中的数据。
如果使用localStorage
,数据将永远存在,除非例如调用localStorage.clear()
23. 下面代码的输出是什么?
var num = 8;
var num = 10;
console.log(num);
A: 8
B: 10
C: SyntaxError
D: ReferenceErr
答案: B
使用var
关键字,您可以用相同的名称声明多个变量。然后变量将保存最新的值。
不能使用let
或const
来实现这一点,因为它们是块作用域的。
24. 下面代码的输出是什么?
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
A: false true false true
B: false true true true
C: true true false true
D: true true true true
答案:C
所有对象键(不包括Symbols)
都会被存储为字符串,即使你没有给定字符串类型的键。 这就是为什么obj.hasOwnProperty('1')
也返回 true
。
上面的说法不适用于Set
。 在我们的Set中没有"1":set.has('1')
返回 false
。 它有数字类型 1
,set.has(1)
返回 true
。
25. 下面代码的输出是什么?
const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
A: { a: "one", b: "two" }
B: { b: "two", a: "three" }
C: { a: "three", b: "two" }
D: SyntaxError
答案: C
如果对象有两个具有相同名称的键,则将替前面的键。它仍将处于第一个位置,但具有最后指定的值。
26. JavaScript全局执行上下文为你创建了两个东西:全局对象和this关键字.
A: 对
B: 错误
C: 视情况而定
答案: A
基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。
27. 下面代码的输出是什么?
for (let i = 1; i < 5; i++) {
if (i === 3) continue;
console.log(i);
}
A: 1 2
B: 1 2 3
C: 1 2 4
D: 1 3 4
答案 C
如果某个条件返回true
,则continue
语句跳过迭代。
28. 下面代码的输出是什么?
String.prototype.giveLydiaPizza = () => {
return "Just give Lydia pizza already!";
};
const name = "Lydia";
name.giveLydiaPizza();
A: "Just give Lydia pizza already!"
B: TypeError: not a function
C: SyntaxError
D: undefined
答案:A
String
是一个内置的构造函数,我们可以为它添加属性。 我刚给它的原型添加了一个方法。 原始类型的字符串自动转换为字符串对象,由字符串原型函数生成。 因此,所有字符串(字符串对象)都可以访问该方法!
当使用基本类型的字符串调用giveLydiaPizza时,实际上发生了下面的过程:
- 创建一个String的包装类型实例
- 在实例上调用substring方法
- 销毁实例
29. 下面代码的输出是什么?
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);
A: 123
B: 456
C: undefined
D: ReferenceError
答案: B
对象键自动转换为字符串。我们试图将一个对象设置为对象 a
的键,其值为123
。 但是,当对象自动转换为字符串化时,它变成了[Object object]
。 所以我们在这里说的是a["Object object"] = 123
。 然后,我们可以尝试再次做同样的事情。 c
对象同样会发生隐式类型转换。那么,a["Object object"] = 456
。 然后,我们打印a[b]
,它实际上是a["Object object"]
。 我们将其设置为456
,因此返回456
。
30. 下面代码的输出是什么?
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");
bar();
foo();
baz();
A: First Second Third
B: First Third Second
C: Second First Third
D: Second Third First
答案: B
31. 单击按钮时event.target是什么?
A: div外部
B: div内部
C: button
D: 所有嵌套元素的数组.
答案 C
导致事件的最深嵌套元素是事件的目标。 你可以通过vent.stopPropagation
停止冒泡
32. 单击下面的html片段打印的内容是什么?
Click here!
A: p div
B: div p
C: p
D: div
答案:A
如果我们单击p
,我们会看到两个日志:p
和div
。在事件传播期间,有三个阶段:捕获,目标和冒泡。 默认情况下,事件处理程序在冒泡阶段执行(除非将useCapture
设置为true
)。 它从最深的嵌套元素向外延伸。
33. 下面代码的输出是什么?
const person = { name: "Lydia" };
function sayHi(age) {
console.log(`${this.name} is ${age}`);
}
sayHi.call(person, 21);
sayHi.bind(person, 21);
A: undefined is 21 Lydia is 21
B: function function
C: Lydia is 21 Lydia is 21
D: Lydia is 21 function
答案: D
使用两者,我们可以传递我们想要this
关键字引用的对象。 但是.call
方法会立即执行!
.bind
方法会返回函数的拷贝值,但带有绑定的上下文! 它不会立即执行。
34. 下面代码的输出是什么?
function sayHi() {
return (() => 0)();
}
typeof sayHi();
A: "object"
B: "number"
C: "function"
D: "undefined"
答案: B
sayHi
函数返回立即调用的函数 (IIFE)
的返回值。 该函数返回0
,类型为数字。 仅供参考:只有7
种内置类型:null,undefined,boolean,number,string,object和symbol
。 function
不是一个类型,因为函数是对象,它的类型是object
。
35. 下面这些值哪些是假值?
0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
A: 0, '', undefined
B: 0, new Number(0), '', new Boolean(false), undefined
C: 0, '', new Boolean(false), undefined
答案: A
JavaScript中只有6个假值:
- undefined
- null
- NaN
- 0
- '' (empty string)
- false
函数构造函数,如new Number
和new Boolean
都是真值。
36. 下面代码的输出是什么?
console.log(typeof typeof 1);
A: "number"
B: "string"
C: "object"
D: "undefined"
答案: B
typeof 1
返回 "number"
. typeof "number"
返回 "string"
37. 下面代码的输出是什么?
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
A: [1, 2, 3, 7 x null, 11]
B: [1, 2, 3, 11]
C: [1, 2, 3, 7 x empty, 11]
D: SyntaxError
答案:C
当你为数组中的元素设置一个超过数组长度的值时,JavaScript
会创建一个名为“空插槽”
的东西。 这些位置的值实际上是undefined
,但你会看到类似的东西: [1, 2, 3, 7 x empty, 11]
这取决于你运行它的位置(每个浏览器有可能不同)。
38. 下面代码的输出是什么?
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);
}
console.log(x);
console.log(y);
})();
A: 1 undefined 2
B: undefined undefined undefined
C: 1 1 2
D: 1 undefined undefined
答案:A
catch
块接收参数 x
。当我们传递参数时,这与变量的x
不同。这个变量x
是属于catch
作用域的。 之后,我们将这个块级作用域的变量设置为1
,并设置变量y
的值。 现在,我们打印块级作用域的变量x
,它等于1
。 在catch
块之外,x
仍然是undefined
,而y
是2
。 当我们想在catch
块之外的console.log(x)
时,它返回undefined
,而y
返回2
。
39. JavaScript中的所有内容都是...
A:原始或对象
B:函数或对象
C:技巧问题!只有对象
D:数字或对象
答案:A
JavaScript
只有原始类型和对象。
原始类型是 boolean
,null
,undefined
,bigint
,number
,string
和symbol
。
40. 下面代码的输出是什么?
[[0, 1], [2, 3]].reduce(
(acc, cur) => {
return acc.concat(cur);
},
[1, 2]
);
A: [0, 1, 2, 3, 1, 2]
B: [6, 1, 2]
C: [1, 2, 0, 1, 2, 3]
D: [1, 2, 6]
答案: C
[1,2]
是我们的初始值。 这是我们开始执行reduce
函数的初始值,以及第一个acc
的值。 在第一轮中,acc
是[1,2]
,cur
是[0,1]
。 我们将它们连接起来,结果是[1,2,0,1]
。 然后,acc
的值为[1,2,0,1]
,cur
的值为[2,3]
。 我们将它们连接起来,得到[1,2,0,1,2,3]
。
41setInterval方法的返回值什么?
setInterval(() => console.log("Hi"), 1000);
A:一个唯一的id
B:指定的毫秒数
C:传递的函数
D:undefined
答案: A
它返回一个唯一的id
。 此id
可用于使用clearInterval()
函数清除该定时器。
42. display:none与visibility:hidden的区别(2018拼多多前端笔试真题)
答案:在视觉效果上,两者是相同的,但是对于操作dom上是不同的 。 dispaly:none 会让dom的整个宽、高等相关位置元素失效,整个消失; visibility:hidden 只是让该元素不可见,但是width以及原有位置是不会改变的
43. 以下两个函数是否等价
function foo1()
{
return { //
bar: "hello"
};
}
function foo2()
{
return
{ //
bar: "hello"
};
}
答案: 不等价!! 注意,第二个函数返回的是undefined
console.log(foo1()); // {bar : "hellp"}
console.log(foo2()); // undefined
44.NaN是什么?它是什么类型?如何检测一个变量是不是NaN?
答案: NaN即Not A Number,但实际上它是Number类型 typeof NaN 将会返回Number。 这个东西比较厉害,因为
NaN === NaN //false
复制代码你会发现,它自己都不等于它自己,因此判断变量是否是它,不能使用===。 可以使用isNaN方法
//检查变量是否是nan
isNaN(bar);
Object.is(bar,NaN); //ES6方法,这个方法会修正JS中的一些小bug
Object.is()方法,要求严格相等,且Object.is(NaN,NaN)会返回true
4.this&对象&数组
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(this);
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: serl.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
分析: 搞清楚this的指向。记住以下几种规则
- 谁调用,this指向谁 xxx.fun()
- new一个对象,this指向实例本身var c = new fun()
- 使用call/apply/bind修改this指向。
看题目,myObject.func
显然是第一种情况,谁调用,this指向谁,这个时候都是myOjbect。 而在立即执行函数中,在这里this是没有进行绑定指向的,自然从属于window,所以这里this.foo是undefied
补充关于箭头函数的this
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()()) //window
注意:箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this。在这个例子中,因为调用 a 符合前面代码中的第一个情况,所以 this 是 window。并且 this 一旦绑定了上下文,就不会被任何代码改变。
数组的filter,以下输出结果是什么(2018拼多多前端原题)
var arr = [1,2,3];
arr[10] = 9;
arr.filter((item)=> {
console.log(item) //1,2,3,9 map也是一样的此处console.log
return item === undefined?
})
//答案
[]
解析: 是的,答案的确是[],不是[undefined x 7]。 首先,看下前两句执行后,arr是什么
console.log(arr)
//[1,2,3, emptyx7, 9]
console.log(arr[5])
//undefined
console.log(1 + "2" + "2"); //122
console.log(1 + +"2" + "2");//32
console.log(1 + -"1" + "2");//02
console.log(+"1" + "1" + "2");//112
console.log( "A" - "B" + "2");//NaN2
console.log( "A" - "B" + 2);//NaN
嗯,核心是以下几点,自己再细细思考
- -和+会隐式转换为Number类型
- 当+ 作为运算符出现在String类型前时,会认为需要字符串拼接,因此会隐式转换为String
- Number包含一个特殊的类型NaN,当对非数字进行Number转换时,会变为这个。
第一题: 第二条,认为需要字符串拼接 1被转换为1,答案122 第二题: 注意到第二个2前面的+号,是符合第一条的,因此第二个2被转换为Number类型,答案为32 第三题: 同理,答案02 第五题: 运用(1)(3),显然是NaN2,第六题同理
对象与继承
请问以下程序中,person1和person2哪个是Person的实例?其proto分别指向谁?
function Person(name) {
this.name = name;
return {name: name}
}
var person1 = new Person('sam');
var person2 = Person('Lily')
答案:
person1和person2都不是Person的实例
它们的'__proto__'指向Object
这题题目的关键就是理解new
的过程,这也是常见的面试题之一了。如果遇到关键字new
,那么,函数就不单单是一个函数了:
- 函数执行,首先隐式建立对象
this
- 执行,绑定this相关的属性,本例中
this.name = name
- 函数最后,隐式的
return this
当然,这里简化了这个过程,但是核心是这几步。 但是如果在隐式返回this
之前,提前返回了一个对象,那么就会退出函数了。 要知道,只有这个this
才是实例本身,它的__proto__
才指向构造函数,如果不能把this
返回出去,那么一切都是徒劳的。因此,这里无论是否new
,都返回的是一个新对象{}
。