[TOC]

2018美团前端面试题,两年经验,你能答对几道?

获取页面元素位置与宽高?
element.clientWidth = content + padding
element.clientHeight = content + padding
element.getBoundingClientRect() 返回值情况
left:包围盒左边 border 以外的边缘距页面左边的距离
right:包围盒右边 border 以外的边缘距页面左边的距离
top:包围盒上边 border 以外的边缘距页面顶部的距离
bottom:包围盒下边 border 以外的便于距页面顶部的距离
width: content + padding + border
height: content + padding + border
注意,设置外边距时外边距合并的情况
requestAnimationFrame 原理?是同步还是异步?
异步,传入的函数在重绘之前调用
开始之前要介绍两个概念:
· 页面可见
当页面被最小化或者被切换成后台标签页时,页面为不可见,浏览器会触发一个 visibilitychange事件,并设置document.hidden属性为true;切换到显示状态时,页面为可见,也同样触发一个 visibilitychange事件,设置document.hidden属性为false。
· 动画帧请求回调函数列表
每个Document都有一个动画帧请求回调函数列表,该列表可以看成是由< handle, callback>元组组成的集合。其中handle是一个整数,唯一地标识了元组在列表中的位置;callback回掉函数,形参为一个时间值的函数(该时间值为动画函数每次开始执行距离第一次执行的毫秒数)。
正餐开始:
写法:Handle=requestanimatonframerequest(函数名);
1).传入一个函数名,自然就是要一直跑啊跑的动画函数了;
2).这个handle返回值可是很重要的,他接着的可是动画函数的灵魂!
该值为浏览器定义的、大于0的整数,唯一标识了该回调函数在列表中位置。
简单点的浏览器执行过程:
看过不少网上写的原理,完整点的要看很久才看明白,今天就给看官们更新个新手简化版本(买手抓饼版本): requestAnimationFrame方法,总结起来,每次调用这个方法时会简单的发生两件事(浏览器处理过程)如下:
1.首先要判断document.hidden属性是否为true,就是浏览器开着才会执行。就像是手抓饼店开着才能去抓。
2.浏览器会清空上一轮的动画函数,这个怎么理解呢?就是说Handle=requestanimatonframerequest(函数名);这一句话调用一次后就被浏览器吃掉了。恩,挺对的,手抓饼吃一次就没了,再想吃要再去买。
3.这个方法返回的handle值会和动画函数,以这样的方式:< handle, callback> 进入到——动画帧请求回调函数列
4.浏览器会遍历动画帧请求回调函数列表,根据handel的值大小,依次去执行相应的动画函数;(这里还有个小前提,马上将到).这个过程就像是排队买手抓饼(我们学校的手抓饼阿姨会先给排队的人每人一个袋子,先拿到袋子的先拿饼)
所以,正确的requestanimatonframerequest其实应该是不断的递归。
如下:
function animate(time) {
//这里写的语句会不断重复
console.log(“买手抓饼”);
id = window.requestAnimationFrame(animate);
}
animate();

补充删掉动画函数的操作:
每天都控制不住去买手抓饼怎么办,答案是:钱用完了就不去了。
同样的,来看上文提到的小前提:
每个回调函数都有一个布尔标识cancelled,该标识初始值为false
浏览器在执行“采样所有动画”的任务时会遍历动画帧请求回调函数列表,判断每个元组的callback的cancelled,如果为false,则执行callback,此时才能看到动画效果啦~
(canaelled=你Y的是不是没钱,false=不是的不是的)—》诺,饼给你!
(非常吐槽,为什么要这么虐心,非要cancel+false, 歪果仁很喜欢负负得正啊)
用法:cancelAnimationFrame(要删除的handle);
最后一个小问题,既然传入的参数并不是控制时间间隔的,那么怎么做到像setInterval一样的效果呢? 用时间去判断吧

var timeOne=Date.now(); //起始时间1
function animate(time) {
console.log(time); //这个time 是每次进入执行动画经过的毫秒数
var timeTwo = Date.now(); //起始时间1
if (timeTwo - timeOne >=1000) { //差值就是中间暂停的时间啦(消化手抓饼)
me.innerHTML = ‘我是’ + number + ‘只小青龙’;
number++;
timeOne = timeTwo;
}
id = requestAnimationFrame(animate);
}
animate();
js事件机制?点击屏幕上一个按钮,事件是如何传播的?
捕获 冒泡
下面代码输出结果?为什么?
Function.prototype.a = ‘a’;
Object.prototype.b = ‘b’;
function Person(){};
var p = new Person();
console.log(‘p.a: ‘+ p.a); // p.a: undefined
console.log(‘p.b: ‘+ p.b); // p.b: b
复制代码
下面代码输出结果?为什么?
const person = {
namea: ‘menglinghua’,
say: function (){
return function (){
console.log(this.namea);
};
}
};
person.say()(); // undefined
复制代码
const person = {
namea: ‘menglinghua’,
say: function (){
return () => {
console.log(this.namea);
};
}
};
person.say()(); // menglinghua
复制代码
下面代码输出结果?为什么?
setTimeout(() => console.log(‘a’), 0);
var p = new Promise((resolve) => {
console.log(‘b’);
resolve();
});
p.then(() => console.log(‘c’));
p.then(() => console.log(‘d’));
console.log(‘e’);
// 结果:b e c d a
// 任务队列优先级:promise.Trick()>promise的回调>setTimeout>setImmediate
复制代码
async function async1() {
console.log(“a”);
await async2(); //执行这一句后,await会让出当前线程,将后面的代码加到任务队列中,然后继续执行函数后面的同步代码
console.log(“b”);

}
async function async2() {
console.log( ‘c’);
}
console.log(“d”);
setTimeout(function () {
console.log(“e”);
},0);
async1();
new Promise(function (resolve) {
console.log(“f”);
resolve();
}).then(function () {
console.log(“g”);
});
console.log(‘h’);
// 谁知道为啥结果不一样?????????????
// 直接在控制台中运行结果: d a c f h g b e
// 在页面的script标签中运行结果:d a c f h b g e
复制代码
js bind 实现机制?手写一个 bind 方法?
// 代码来自书籍 《javaScript 模式》
if (typeof Function.prototype.bind === “undefined”){
Function.prototype.bind = function (thisArgs){
var fn = this,
slice = Array.prototype.slice,
args = slice.call(arguments, 1);
return function (){
return fn.apply(thisArgs, args.concat(slice.call(arguments)));
}
}
}
复制代码
实现 vue 中的 on,emit,off,once,手写代码。
// 参照 vue 源码实现
var EventEmiter = function (){
this._events = {};
};
EventEmiter.prototype.on = function (event, cb){
if (Array.isArray(event)){
for (let i = 0, l = event.length; i < l; i++){
this.on(event[i], cb);
}
} else {
(this._events[event] || (this._events[event] = [])).push(cb);
}
return this;
};
EventEmiter.prototype.once = function (event, cb){
function on () {
this.off(event, cb);
cb.apply(this, arguments);
}
on.fn = cb;
this.on(event, on);
return this;
};
EventEmiter.prototype.off = function (event, cb){
if (!arguments.length){
this._events = Object.create(null);
return this;
}
if (Array.isArray(event)){
for (let i = 0, l = event.length; i < l; i++){
this.off(event[i],cb);
}
return this;
}
if (!cb){
this._events[event] = null;
return this;
}
if (cb){
let cbs = this._events[event];
let i = cbs.length;
while(i—){
if (cb === cbs[i] || cb === cbs[i].fn){
cbs.splice(i, 1);
break;
}
}
return this;
}
};
EventEmiter.prototype.emit = function (event){
let cbs = this._events[event];
let args = Array.prototype.slice.call(arguments, 1);
if (cbs){
for (let i = 0, l = cbs.length; i < l; i++){
cbs[i].apply(this,args);
}
}
};
用 js 实现双链表,手写代码?
vue 的双向绑定机制?详细介绍。
哪些操作会引起浏览器重绘和重排?
postion:absolute; left:100px;会不会引起?
translateX:100px;会不会引起?
getBoundingClientRect会不会引起?
getClientWidth、getClientHeight会不会引起?
页面性能监测?

从基础到进阶,200道JavaScript题目

我在我的 Instagram 上每天都会发布 JavaScript 的多选问题,并且同时也会在这个仓库中发布。
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
在函数内部,我们首先通过 var 关键字声明了 name 变量。这意味着变量被提升了(内存空间在创建阶段就被设置好了),直到程序运行到定义变量位置之前默认值都是 undefined。因为当我们打印 name 变量时还没有执行到定义变量的位置,因此变量的值保持为 undefined。
通过 let 和 const 关键字声明的变量也会提升,但是和 var 不同,它们不会被初始化。在我们声明(初始化)之前是不能访问它们的。这个行为被称之为暂时性死区。当我们试图在声明之前访问它们时,JavaScript 将会抛出一个 ReferenceError 错误。
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 和 0 1 2
B: 0 1 2 和 3 3 3
C: 3 3 3 和 0 1 2
答案
答案: C
由于 JavaScript 的事件循环,setTimeout 回调会在遍历结束后才执行。因为在第一个遍历中遍历 i 是通过 var 关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符 ++ 来每次递增 i 的值。当 setTimeout 回调执行的时候,i 的值等于 3。
在第二个遍历中,遍历 i 是通过 let 关键字声明的:通过 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 时,this 不是指向 shape 对象,而是它的周围作用域(在例子中是 window)。
在 window 中没有 radius 这个属性,因此返回 undefined。
4. 输出是什么?
+true;
!”Lydia”;
复制代码
A: 1 and false
B: false and NaN
C: false and false
答案
答案: A
一元操作符加号尝试将 bool 转为 number。true 转换为 number 的话为 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 中,所有对象的 keys 都是字符串(除非对象是 Symbol)。尽管我们可能不会定义它们为字符串,但它们在底层总会被转换为字符串。
当我们使用括号语法时([]),JavaScript 会解释(或者 unboxes)语句。它首先看到第一个开始括号 [ 并继续前进直到找到结束括号 ]。只有这样,它才会计算语句的值。
mouse[bird.size]:首先计算 bird.size,这会得到 small。mouse[“small”] 返回 true。
然后使用点语法的话,上面这一切都不会发生。mouse 没有 bird 这个 key,这也就意味着 mouse.bird 是 undefined。然后当我们使用点语法 mouse.bird.size 时,因为 mouse.bird 是 undefined,这也就变成了 undefined.size。这个行为是无效的,并且会抛出一个错误类似 Cannot read property “size” of undefined。
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
在 JavaScript 中,当设置两个对象彼此相等时,它们会通过引用进行交互。
首先,变量 c 的值是一个对象。接下来,我们给 d 分配了一个和 c 对象相同的引用。
WEB   试题 - 图1
因此当我们改变其中一个对象时,其实是改变了所有的对象。
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() 是一个内建的函数构造器。虽然它看着像是一个 number,但它实际上并不是一个真实的 number:它有一堆额外的功能并且它是一个对象。
当我们使用 == 操作符时,它只会检查两者是否拥有相同的值。因为它们的值都是 3,因此返回 true。
然后,当我们使用 === 操作符时,两者的值以及类型都应该是相同的。new Number() 是一个对象而不是 number,因此返回 false。
8. 输出是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor
return this.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 是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是 Chameleon),并且不能传递给实例。因为 freddie 是一个实例,静态方法不能被实例使用,因此抛出了 TypeError 错误。
9. 输出是什么?
let greeting
greetign = {} // Typo!
console.log(greetign)
复制代码
A: {}
B: ReferenceError: greetign is not defined
C: undefined
答案
答案: A
代码打印出了一个对象,这是因为我们在全局对象上创建了一个空对象!当我们将 greeting 写错成 greetign 时,JS 解释器实际在上浏览器中将它视为 global.greetign = {} (或者 window.greetign = {})。
为了避免这个为题,我们可以使用 `”use strict”。这能确保当你声明变量时必须赋值。
10. 当我们这么做时,会发生什么?
function bark() {
console.log(‘Woof!’)
}

bark.animal = ‘dog’
复制代码
A: 正常运行!
B: SyntaxError. 你不能通过这种方式给函数增加属性。
C: undefined
D: ReferenceError
答案
答案: A
这在 JavaScript 中是可以的,因为函数是对象!(除了基本类型之外其他都是对象)
函数是一个特殊的对象。你写的这个代码其实不是一个实际的函数。函数是一个拥有属性的对象,并且属性也可被调用。
11. 输出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

const member = new Person(“Lydia”, “Hallie”);
Person.getFullName = function () {
return ${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 时,this 引用我们创建的空对象。当未使用 new 时,this 引用的是全局对象(global object)。
我们说 this.firstName 等于 “Sarah”,并且 this.lastName 等于 “Smith”。实际上我们做的是,定义了 global.firstName = ‘Sarah’ 和 global.lastName = ‘Smith’。而 sarah 本身是 undefined。
13. 事件传播的三个阶段是什么?
A: Target > Capturing > Bubbling
B: Bubbling > Target > Capturing
C: Target > Bubbling > Capturing
D: Capturing > Target > Bubbling
答案
答案: D
捕获(capturing)阶段中,事件从祖先元素向下传播到目标元素。当事件达到目标(target)元素后,冒泡(bubbling)才开始。
WEB   试题 - 图2
14. 所有对象都有原型。
A: true
B: false
答案
答案: B
除了基本对象(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如 .toString。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。
15. 输出是什么?
function sum(a, b) {
return a + b
}

sum(1, ‘2’)
复制代码
A: NaN
B: TypeError
C: “12”
D: 3
答案
答案: C
JavaScript 是一种动态类型语言:我们不指定某些变量的类型。值可以在你不知道的情况下自动转换成另一种类型,这种类型称为隐式类型转换(implicit type coercion)。Coercion 是指将一种类型转换为另一种类型。
在本例中,JavaScript 将数字 1 转换为字符串,以便函数有意义并返回一个值。在数字类型(1)和字符串类型(’2’)相加时,该数字被视为字符串。我们可以连接字符串,比如 “Hello” + “World”,这里发生的是 “1” + “2”,它返回 “12”。
16. 输出是什么?
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
一元后自增运算符 ++:
返回值(返回 0)
值自增(number 现在是 1)
一元前自增运算符 ++:
值自增(number 现在是 2)
返回值(返回 2)
结果是 0 2 2.
17. 输出是什么?
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
如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!
18. 输出是什么?
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
在测试相等性时,基本类型通过它们的值(value)进行比较,而对象通过它们的引用(reference)进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。
题目中我们正在比较的两个对象不是同一个引用:作为参数传递的对象引用的内存位置,与用于判断相等的对象所引用的内存位置并不同。
这也是 { age: 18 } === { age: 18 } 和 { age: 18 } == { age: 18 } 都返回 false 的原因。
19. 输出是什么?
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”,它将抛出一个引用错误。如果我们不使用 “use strict”,它就会工作,因为属性 age 会被添加到全局对象中了。
21. 输出是什么?
const sum = eval(‘1010+5’)
复制代码
A: 105
B: “105”
C: TypeError
D: “10
10+5”
答案
答案: A
代码以字符串形式传递进来,eval 对其求值。如果它是一个表达式,就像本例中那样,它对表达式求值。表达式是 10 10 + 5。这将返回数字 105。
22. cool_secret 可访问多长时间?
sessionStorage.setItem(‘cool_secret’, 123)
复制代码
A: 永远,数据不会丢失。
B: 当用户关掉标签页时。
C: 当用户关掉整个浏览器,而不只是关掉标签页。
D: 当用户关闭电脑时。
答案
答案: B
关闭 *tab 标签页
后,sessionStorage 存储的数据才会删除。
如果使用 localStorage,那么数据将永远在那里,除非调用了 localStorage.clear()。
23. 输出是什么?
var num = 8
var num = 10

console.log(num)
复制代码
A: 8
B: 10
C: SyntaxError
D: ReferenceError
答案
答案: 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
所有对象的键(不包括 Symbol)在底层都是字符串,即使你自己没有将其作为字符串输入。这就是为什么 obj.hasOwnProperty(‘1’) 也返回 true。
对于集合,它不是这样工作的。在我们的集合中没有 ‘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: true
B: false
C: it depends
答案
答案: 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 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象)都可以访问该方法!
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
对象的键被自动转换为字符串。我们试图将一个对象 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
我们有一个 setTimeout 函数,并首先调用它。然而,它是最后打印日志的。
这是因为在浏览器中,我们不仅有运行时引擎,还有一个叫做 WebAPI 的东西。WebAPI 提供了 setTimeout 函数,也包含其他的,例如 DOM。
将 callback 推送到 WebAPI 后,setTimeout 函数本身(但不是回调!)将从栈中弹出。
WEB   试题 - 图3
现在,foo 被调用,打印 “First”。
WEB   试题 - 图4
foo 从栈中弹出,baz 被调用. 打印 “Third”。
WEB   试题 - 图5
WebAPI 不能随时向栈内添加内容。相反,它将回调函数推到名为 queue 的地方。
WEB   试题 - 图6
这就是事件循环开始工作的地方。一个事件循环查看栈和任务队列。如果栈是空的,它接受队列上的第一个元素并将其推入栈。
WEB   试题 - 图7
bar 被调用,打印 “Second”,然后它被栈弹出。
31. 当点击按钮时,event.target是什么?






复制代码
A: Outer div
B: Inner div
C: button
D: 一个包含所有嵌套元素的数组。
答案
答案: C
导致事件的最深嵌套的元素是事件的 target。你可以通过 event.stopPropagation 来停止冒泡。
32. 当您单击该段落时,日志输出是什么?


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, 类型是 number
参考:只有7种内置类型:null,undefined,boolean,number,string,object 和 symbol。 function 不是一种类型,函数是对象,它的类型是object。
35. 下面哪些值是 falsy?
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
D: All of them are falsy
答案
答案: A
只有 6 种 falsy 值:
undefined
null
NaN
0
‘’ (empty string)
false
Function 构造函数, 比如 new Number 和 new Boolean,是 truthy
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 会创建名为 “empty slots” 的东西。它们的值实际上是 undefined。你会看到以下场景:
[1, 2, 3, 7 x empty, 11]
这取决于你的运行环境(每个浏览器,以及 node 环境,都有可能不同)
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]是初始值。初始值将会作为首次调用时第一个参数 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]
41. 输出是什么?
!!null
!!’’
!!1
复制代码
A: false true false
B: false false true
C: false true true
D: true true false
答案
答案: B
null 是 falsy。 !null 的值是 true。 !true 的值是 false。
“” 是 falsy。 !”” 的值是 true。 !true 的值是 false。
1 是 truthy。 !1 的值是 false。 !false 的值是 true。
42. setInterval 方法的返回值是什么?
setInterval(() => console.log(‘Hi’), 1000)
复制代码
A: 一个唯一的id
B: 该方法指定的毫秒数
C: 传递的函数
D: undefined
答案
答案: A
setInterval 返回一个唯一的 id。此 id 可被用于 clearInterval 函数来取消定时。
43. 输出是什么?
[…’Lydia’]
复制代码
A: [“L”, “y”, “d”, “i”, “a”]
B: [“Lydia”]
C: [[], “Lydia”]
D: [[“L”, “y”, “d”, “i”, “a”]]
答案
答案: A
string 类型是可迭代的。扩展运算符将迭代的每个字符映射成一个元素。
44. 输出是什么?
function generator(i) {
yield i;
yield i
2;
}

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
复制代码
A: [0, 10], [10, 20]
B: 20, 20
C: 10, 20
D: 0, 10 and 10, 20
答案
答案: C
一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到yield关键字的时候,会生成yield后面的值。注意,生成器在这种情况下不 返回 (return )值,而是 生成 (yield)值。
首先,我们用10作为参数i来初始化生成器函数。然后使用next()方法一步步执行生成器。第一次执行生成器的时候,i的值为10,遇到第一个yield关键字,它要生成i的值。此时,生成器“暂停”,生成了10。
然后,我们再执行next()方法。生成器会从刚才暂停的地方继续,这个时候i还是10。于是我们走到了第二个yield关键字处,这时候需要生成的值是i*2,i为10,那么此时生成的值便是20。所以这道题的最终结果是10,20。
45. 返回值是什么?
const firstPromise = new Promise((res, rej) => {
setTimeout(res, 500, “one”);
});

const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, “two”);
});

Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
复制代码
A: “one”
B: “two”
C: “two” “one”
D: “one” “two”
答案
答案: B
当我们向Promise.race方法中传入多个Promise时,会进行 优先 解析。在这个例子中,我们用setTimeout给firstPromise和secondPromise分别设定了500ms和100ms的定时器。这意味着secondPromise会首先解析出字符串two。那么此时res参数即为two,是为输出结果。
46. 输出是什么?
let person = { name: “Lydia” };
const members = [person];
person = null;

console.log(members);
复制代码
A: null
B: [null]
C: [{}]
D: [{ name: “Lydia” }]
答案
答案: D
首先我们声明了一个拥有name属性的对象 person。
然后我们又声明了一个变量members. 将首个元素赋值为变量person。 当设置两个对象彼此相等时,它们会通过 引用 进行交互。但是当你将引用从一个变量分配至另一个变量时,其实只是执行了一个 复制 操作。(注意一点,他们的引用 并不相同!)
接下来我们让person等于null。
我们没有修改数组第一个元素的值,而只是修改了变量person的值,因为元素(复制而来)的引用与person不同。members的第一个元素仍然保持着对原始对象的引用。当我们输出members数组时,第一个元素会将引用的对象打印出来。
47. 输出是什么?
const person = {
name: “Lydia”,
age: 21
};

for (const item in person) {
console.log(item);
}
复制代码
A: { name: “Lydia” }, { age: 21 }
B: “name”, “age”
C: “Lydia”, 21
D: [“name”, “Lydia”], [“age”, 21]
答案
答案: B
在for-in循环中,我们可以通过对象的key来进行迭代,也就是这里的name和age。在底层,对象的key都是字符串(如果他们不是Symbol的话)。在每次循环中,我们将item设定为当前遍历到的key.所以一开始,item是name,之后 item输出的则是age。
48. 输出是什么?
console.log(3 + 4 + “5”);
复制代码
A: “345”
B: “75”
C: 12
D: “12”
答案
答案: B
当所有运算符的 优先级 相同时,计算表达式需要确定运算符的结合顺序,即从右到左还是从左往右。在这个例子中,我们只有一类运算符+,对于加法来说,结合顺序就是从左到右。
3 + 4首先计算,得到数字7.
由于类型的强制转换,7 + ‘5’的结果是”75”. JavaScript将7转换成了字符串,可以参考问题15.我们可以用+号把两个字符串连接起来。 “7” + “5” 就得到了”75”.
49. num的值是什么?
const num = parseInt(“76”, 10);
复制代码
A: 42
B: “42”
C: 7
D: NaN
答案
答案: C
只返回了字符串中第一个字母. 设定了 进制 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),parseInt 检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。
就是不合法的数字字符。所以只解析到”7”,并将其解析为十进制的7. num的值即为7.
50. 输出是什么?
[1, 2, 3].map(num => {
if (typeof num === “number”) return;
return num * 2;
});
复制代码
A: []
B: [null, null, null]
C: [undefined, undefined, undefined]
D: [ 3 x empty ]
答案
答案: C
对数组进行映射的时候,num就是当前循环到的元素. 在这个例子中,所有的映射都是number类型,所以if中的判断typeof num === “number”结果都是true.map函数创建了新数组并且将函数的返回值插入数组。
但是,没有任何值返回。当函数没有返回任何值时,即默认返回undefined.对数组中的每一个元素来说,函数块都得到了这个返回值,所以结果中每一个元素都是undefined.
51. 输出的是什么?
function getInfo(member, year) {
member.name = “Lydia”;
year = “1998”;
}

const person = { name: “Sarah” };
const birthYear = “1997”;

getInfo(person, birthYear);

console.log(person, birthYear);
复制代码
A: { name: “Lydia” }, “1997”
B: { name: “Sarah” }, “1998”
C: { name: “Lydia” }, “1998”
D: { name: “Sarah” }, “1997”
答案
答案: A
普通参数都是 值 传递的,而对象则不同,是 引用 传递。所以说,birthYear是值传递,因为他是个字符串而不是对象。当我们对参数进行值传递时,会创建一份该值的 复制 。(可以参考问题46)
变量birthYear有一个对”1997”的引用,而传入的参数也有一个对”1997”的引用,但二者的引用并不相同。当我们通过给 year赋值”1998”来更新year的值的时候我们只是更新了year(的引用)。此时birthYear仍然是”1997”.
而person是个对象。参数member引用与之 相同的 对象。当我们修改member所引用对象的属性时,person的相应属性也被修改了,因为他们引用了相同的对象. person的 name属性也变成了 “Lydia”.
52. 输出是什么?
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();
复制代码
A: “It worked! Hello world!”
B: “Oh no an error: undefined
C: SyntaxError: can only throw Error objects
D: “Oh no an error: Hello world!
答案
答案: D
通过throw语句,我么可以创建自定义错误。 而通过它,我们可以抛出异常。异常可以是一个字符串, 一个 数字, 一个 布尔类型 或者是一个 对象。在本例中,我们的异常是字符串’Hello world’.
通过 catch语句,我们可以设定当try语句块中抛出异常后应该做什么处理。在本例中抛出的异常是字符串’Hello world’. e就是这个字符串,因此被输出。最终结果就是’Oh an error: Hello world’.
53. 输出是什么?
function Car() {
this.make = “Lamborghini”;
return { make: “Maserati” };
}

const myCar = new Car();
console.log(myCar.make);
复制代码
A: “Lamborghini”
B: “Maserati”
C: ReferenceError
D: TypeError
答案
答案: B
返回属性的时候,属性的值等于 返回的 值,而不是构造函数中设定的值。我们返回了字符串 “Maserati”,所以 myCar.make等于”Maserati”.
54. 输出是什么?
(() => {
let x = (y = 10);
})();

console.log(typeof x);
console.log(typeof y);
复制代码
A: “undefined”, “number”
B: “number”, “number”
C: “object”, “number”
D: “number”, “undefined”
答案
答案: A
let x = y = 10; 是下面这个表达式的缩写:
y = 10;
let x = y;
复制代码
我们设定y等于10时,我们实际上增加了一个属性y给全局对象(浏览器里的window, Nodejs里的global)。在浏览器中, window.y等于10.
然后我们声明了变量x等于y,也是10.但变量是使用 let声明的,它只作用于 块级作用域, 仅在声明它的块中有效;就是案例中的立即调用表达式(IIFE)。使用typeof操作符时, 操作值 x没有被定义:因为我们在x声明块的外部,无法调用它。这就意味着x未定义。未分配或是未声明的变量类型为”undefined”. console.log(typeof x)返回”undefined”.
而我们创建了全局变量y,并且设定y等于10.这个值在我们的代码各处都访问的到。 y已经被定义了,而且有一个”number”类型的值。 console.log(typeof y)返回”number”.
55. 输出是什么?
class Dog {
constructor(name) {
this.name = name;
}
}

Dog.prototype.bark = function() {
console.log(Woof I am ${this.name});
};

const pet = new Dog(“Mara”);

pet.bark();

delete Dog.prototype.bark;

pet.bark();
复制代码
A: “Woof I am Mara”, TypeError
B: “Woof I am Mara”,”Woof I am Mara”
C: “Woof I am Mara”, undefined
D: TypeError, TypeError
答案
答案: A
我们可以用delete关键字删除对象的属性,对原型也是适用的。删除了原型的属性后,该属性在原型链上就不可用了。在本例中,函数bark在执行了delete Dog.prototype.bark后不可用, 然而后面的代码还在调用它。
当我们尝试调用一个不存在的函数时TypeError异常会被抛出。在本例中就是 TypeError: pet.bark is not a function,因为pet.bark是undefined.
56. 输出是什么?
const set = new Set([1, 1, 2, 3, 4]);

console.log(set);
复制代码
A: [1, 1, 2, 3, 4]
B: [1, 2, 3, 4]
C: {1, 1, 2, 3, 4}
D: {1, 2, 3, 4}
答案
答案: D
Set对象是独一无二的值的集合:也就是说同一个值在其中仅出现一次。
我们传入了数组[1, 1, 2, 3, 4],他有一个重复值1.以为一个集合里不能有两个重复的值,其中一个就被移除了。所以结果是 {1, 2, 3, 4}.
57. 输出是什么?
// counter.js
let counter = 10;
export default counter;
复制代码
// index.js
import myCounter from “./counter”;

myCounter += 1;

console.log(myCounter);
复制代码
A: 10
B: 11
C: Error
D: NaN
答案
答案: C
引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。
当我们给myCounter增加一个值的时候会抛出一个异常: myCounter是只读的,不能被修改。
58. 输出是什么?
const name = “Lydia”;
age = 21;

console.log(delete name);
console.log(delete age);
复制代码
A: false, true
B: “Lydia”, 21
C: true, true
D: undefined, undefined
答案
答案: A
delete操作符返回一个布尔值: true指删除成功,否则返回false. 但是通过 var, const 或 let 关键字声明的变量无法用 delete 操作符来删除。
name变量由const关键字声明,所以删除不成功:返回 false. 而我们设定age等于21时,我们实际上添加了一个名为age的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以delete age返回true.
59. 输出是什么?
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;

console.log(y);
复制代码
A: [[1, 2, 3, 4, 5]]
B: [1, 2, 3, 4, 5]
C: 1
D: [1]
答案
答案: C
我们可以通过解构赋值来解析来自对象的数组或属性的值,比如说:
[a, b] = [1, 2];
a的值现在是1,b的值现在是2.而在题目中,我们是这么做的:
[y] = [1, 2, 3, 4, 5];
也就是说,y等于数组的第一个值就是数字1.我们输出y, 返回1.
60. 输出是什么?
const user = { name: “Lydia”, age: 21 };
const admin = { admin: true, …user };

console.log(admin);
复制代码
A: { admin: true, user: { name: “Lydia”, age: 21 } }
B: { admin: true, name: “Lydia”, age: 21 }
C: { admin: true, user: [“Lydia”, 21] }
D: { admin: true }
答案
答案: B
扩展运算符…为对象的组合提供了可能。你可以复制对象中的键值对,然后把它们加到另一个对象里去。在本例中,我们复制了user对象键值对,然后把它们加入到admin对象中。admin对象就拥有了这些键值对,所以结果为{ admin: true, name: “Lydia”, age: 21 }.
61. 输出是什么?
const person = { name: “Lydia” };

Object.defineProperty(person, “age”, { value: 21 });

console.log(person);
console.log(Object.keys(person));
复制代码
A: { name: “Lydia”, age: 21 }, [“name”, “age”]
B: { name: “Lydia”, age: 21 }, [“name”]
C: { name: “Lydia”}, [“name”, “age”]
D: { name: “Lydia”}, [“age”]
答案
答案: B
通过defineProperty方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用defineProperty方法给对象添加了一个属性之后,属性默认为 不可枚举(not enumerable). Object.keys方法仅返回对象中 可枚举(enumerable) 的属性,因此只剩下了”name”.
用defineProperty方法添加的属性默认不可变。你可以通过writable, configurable 和 enumerable属性来改变这一行为。这样的话, 相比于自己添加的属性,defineProperty方法添加的属性有了更多的控制权。
62. 输出是什么?
const settings = {
username: “lydiahallie”,
level: 19,
health: 90
};

const data = JSON.stringify(settings, [“level”, “health”]);
console.log(data);
复制代码
A: “{“level”:19, “health”:90}”
B: “{“username”: “lydiahallie”}”
C: “[“level”, “health”]”
D: “{“username”: “lydiahallie”, “level”:19, “health”:90}”
答案
答案: A
JSON.stringify的第二个参数是 替代者(replacer). 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。
如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为”level” 和 “health” 的属性被包括进来, “username”则被排除在外。 data 就等于 “{“level”:19, “health”:90}”.
而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。 函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为undefined,则该属性会被排除在外。
63. 输出是什么?
let num = 10;

const increaseNumber = () => num++;
const increasePassedNumber = number => number++;

const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);

console.log(num1);
console.log(num2);
复制代码
A: 10, 10
B: 10, 11
C: 11, 11
D: 11, 12
答案
答案: A
一元操作符 ++ 先返回 操作值, 再累加 操作值。num1的值是10, 因为increaseNumber函数首先返回num的值,也就是10,随后再进行 num的累加。
num2是10因为我们将 num1传入increasePassedNumber. number等于10(num1的值。同样道理,++ 先返回 操作值, 再累加 操作值。) number是10,所以num2也是10.
64. 输出什么?
const value = { number: 10 };

const multiply = (x = { …value }) => {
console.log(x.number *= 2);
};

multiply();
multiply();
multiply(value);
multiply(value);
复制代码
A: 20, 40, 80, 160
B: 20, 40, 20, 40
C: 20, 20, 20, 40
D: NaN, NaN, 20, 40
答案
答案: C
在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 “undefined” ,那么参数的值将是默认值。上述例子中,我们将 value 对象进行了解构并传到一个新对象中,因此 x 的默认值为 {number:10} 。
默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 multiply 函数且不传递值,那么每一次 x 的默认值都为 {number:10} ,因此打印出该数字的乘积值为20。
第三次调用 multiply 时,我们传递了一个参数,即对象value。 =运算符实际上是x.number = x.number 2的简写,我们修改了x.number的值,并打印出值20。
第四次,我们再次传递value对象。 x.number之前被修改为20,所以x.number * = 2打印为40。
65. 输出什么?
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
复制代码
A: 1 2 and 3 3 and 6 4
B: 1 2 and 2 3 and 3 4
C: 1 undefined and 2 undefined and 3 undefined and 4 undefined
D: 1 2 and undefined 3 and undefined 4
答案
答案: D
reducer 函数接收4个参数:
Accumulator (acc) (累计器)
Current Value (cur) (当前值)
Current Index (idx) (当前索引)
Source Array (src) (源数组)
reducer 函数的返回值将会分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。
reducer 函数还有一个可选参数initialValue, 该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供initialValue,则将使用数组中的第一个元素。
在上述例子,reduce方法接收的第一个参数(Accumulator)是x, 第二个参数(Current Value)是y。
在第一次调用时,累加器x为1,当前值“y”为2,打印出累加器和当前值:1和2。
例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回undefined。 在下一次调用时,累加器为undefined,当前值为“3”, 因此undefined和3被打印出。
在第四次调用时,回调函数依然没有返回值。 累加器再次为 undefined ,当前值为“4”。 undefined和4被打印出。
66. 使用哪个构造函数可以成功继承Dog类?
class Dog {
constructor(name) {
this.name = name;
}
};

class Labrador extends Dog {
// 1
constructor(name, size) {
this.size = size;
}
// 2
constructor(name, size) {
super(name);
this.size = size;
}
// 3
constructor(size) {
super(name);
this.size = size;
}
// 4
constructor(name, size) {
this.name = name;
this.size = size;
}

};
复制代码
A: 1
B: 2
C: 3
D: 4
答案
答案: B
在子类中,在调用super之前不能访问到this关键字。 如果这样做,它将抛出一个ReferenceError:1和4将引发一个引用错误。
使用super关键字,需要用给定的参数来调用父类的构造函数。 父类的构造函数接收name参数,因此我们需要将name传递给super。
Labrador类接收两个参数,name参数是由于它继承了Dog,size作为Labrador类的额外属性,它们都需要传递给Labrador的构造函数,因此使用构造函数2正确完成。
67. 输出什么?
// 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;
复制代码
A: running index.js, running sum.js, 3
B: running sum.js, running index.js, 3
C: running sum.js, 3, running index.js
D: running index.js, undefined, running sum.js
答案
答案: B
import命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
这是CommonJS中require()和import之间的区别。使用require(),您可以在运行代码时根据需要加载依赖项。 如果我们使用require而不是import,running index.js,running sum.js,3会被依次打印。
68. 输出什么?
console.log(Number(2) === Number(2))
console.log(Boolean(false) === Boolean(false))
console.log(Symbol(‘foo’) === Symbol(‘foo’))
复制代码
A: true, true, false
B: false, true, false
C: true, false, true
D: true, true, true
答案
答案: A
每个Symbol都是完全唯一的。传递给Symbol的参数只是给Symbol的一个描述。 Symbol的值不依赖于传递的参数。 当我们测试相等时,我们创建了两个全新的符号:第一个Symbol(’foo’),第二个Symbol(’foo’), 这两个值是唯一的,彼此不相等,因此返回false。
69. 输出什么?
const name = “Lydia Hallie”
console.log(name.padStart(13))
console.log(name.padStart(2))
复制代码
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方法的参数小于字符串的长度,则不会添加填充。
70. 输出什么?
console.log(“🥑” + “💻”);
复制代码
A: “🥑💻”
B: 257548
C: A string containing their code points
D: Error
答案
答案: A
使用+运算符,您可以连接字符串。 上述情况,我们将字符串“🥑”与字符串”💻“连接起来,产生”🥑💻“。
71. 如何能打印出console.log语句后注释掉的值?
function* startGame() {
const answer = yield “Do you love JavaScript?”;
if (answer !== “Yes”) {
return “Oh wow… Guess we’re gone here”;
}
return “JavaScript loves you back ❤️”;
}

const game = startGame();
console.log(/ 1 /); // Do you love JavaScript?
console.log(/ 2 /); // JavaScript loves you back ❤️
复制代码
A: game.next(“Yes”).value and game.next().value
B: game.next.value(“Yes”) and game.next.value()
C: game.next().value and game.next(“Yes”).value
D: game.next.value() and game.next.value(“Yes”)
答案
答案: C
generator函数在遇到yield关键字时会“暂停”其执行。 首先,我们需要让函数产生字符串Do you love JavaScript?,这可以通过调用game.next().value来完成。上述函数的第一行就有一个yield关键字,那么运行立即停止了,yield表达式本身没有返回值,或者说总是返回undefined, 这意味着此时变量 answer 为undefined
next方法可以带一个参数,该参数会被当作上一个 yield 表达式的返回值。当我们调用game.next(“Yes”).value时,先前的 yield 的返回值将被替换为传递给next()函数的参数”Yes”。此时变量 answer 被赋值为 “Yes”,if语句返回false,所以JavaScript loves you back ❤️被打印。
72. 输出什么?
console.log(String.rawHello\nworld);
复制代码
A: Hello world!
B: Hello
world
C: Hello\nworld
D: Hello\n
world
答案
答案: C
String.raw函数是用来获取一个模板字符串的原始字符串的,它返回一个字符串,其中忽略了转义符(\n,\v,\t等)。但反斜杠可能造成问题,因为你可能会遇到下面这种类似情况:
const path = C:\Documents\Projects\table.html
String.raw${path}
复制代码
这将导致:
“C:DocumentsProjects able.html”
直接使用String.raw
String.rawC:\Documents\Projects\table.html
复制代码
它会忽略转义字符并打印:C:\Documents\Projects\table.html
上述情况,字符串是Hello\nworld被打印出。
73. 输出什么?
async function getData() {
return await Promise.resolve(“I made it!”);
}

const data = getData();
console.log(data);
复制代码
A: “I made it!”
B: Promise {: “I made it!”}
C: Promise {}
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!”
74. 输出什么?
function addToList(item, list) {
return list.push(item);
}

const result = addToList(“apple”, [“banana”]);
console.log(result);
复制代码
A: [‘apple’, ‘banana’]
B: 2
C: true
D: undefined
答案
答案: B
push()方法返回新数组的长度。一开始,数组包含一个元素(字符串”banana”),长度为1。 在数组中添加字符串”apple”后,长度变为2,并将从addToList函数返回。
push方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在push item之后返回list。
75. 输出什么?
const box = { x: 10, y: 20 };

Object.freeze(box);

const shape = box;
shape.x = 100;
console.log(shape)
复制代码
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异常(最常见但不仅限于严格模式下时)。
76. 输出什么?
const { name: myName } = { name: “Lydia” };

console.log(name);
复制代码
A: “Lydia”
B: “myName”
C: undefined
D: ReferenceError
答案
答案: D
当我们从右侧的对象解构属性name时,我们将其值Lydia分配给名为myName的变量。
使用{name:myName},我们是在告诉JavaScript我们要创建一个名为myName的新变量,并且其值是右侧对象的name属性的值。
当我们尝试打印name,一个未定义的变量时,就会引发ReferenceError。
77. 以下是个纯函数么?
function sum(a, b) {
return a + b;
}
复制代码
A: Yes
B: No
答案
答案: A
纯函数一种若输入参数相同,则永远会得到相同输出的函数。
sum函数总是返回相同的结果。 如果我们传递1和2,它将总是返回3而没有副作用。 如果我们传递5和10,它将总是返回15,依此类推,这是纯函数的定义。
78. 输出什么?
const add = () => {
const cache = {};
return num => {
if (num in cache) {
return From cache! ${cache[num]};
} else {
const result = num + 10;
cache[num] = result;
return Calculated! ${result};
}
};
};

const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 2));
复制代码
A: Calculated! 20 Calculated! 20 Calculated! 20
B: Calculated! 20 From cache! 20 Calculated! 20
C: Calculated! 20 From cache! 20 From cache! 20
D: Calculated! 20 From cache! 20 Error
答案
答案: C
add函数是一个记忆函数。 通过记忆化,我们可以缓存函数的结果,以加快其执行速度。上述情况,我们创建一个cache对象,用于存储先前返回过的值。
如果我们使用相同的参数多次调用addFunction函数,它首先检查缓存中是否已有该值,如果有,则返回缓存值,这将节省执行时间。如果没有,那么它将计算该值,并存储在缓存中。
我们用相同的值三次调用了addFunction函数:
在第一次调用,num等于10时函数的值尚未缓存,if语句num in cache返回false,else块的代码被执行:Calculated! 20,并且其结果被添加到缓存对象,cache现在看起来像{10:20}。
第二次,cache对象包含10的返回值。 if语句 num in cache 返回true,From cache! 20被打印。
第三次,我们将5
2(值为10)传递给函数。 cache对象包含10的返回值。 if语句 num in cache 返回true,From cache! 20被打印。
79. 输出什么?
const myLifeSummedUp = [“☕”, “💻”, “🍷”, “🍫”]

for (let item in myLifeSummedUp) {
console.log(item)
}

for (let item of myLifeSummedUp) {
console.log(item)
}
复制代码
A: 0 1 2 3 and “☕” “💻” “🍷” “🍫”
B: “☕” “💻” “🍷” “🍫” and “☕” “💻” “🍷” “🍫”
C: “☕” “💻” “🍷” “🍫” and 0 1 2 3
D: 0 1 2 3 and {0: “☕”, 1: “💻”, 2: “🍷”, 3: “🍫”}
答案
答案: A
通过for-in循环,我们可以遍历一个对象自有的继承的可枚举的非Symbol的属性。 在数组中,可枚举属性是数组元素的“键”, 即它们的索引。 类似于下面这个对象:
{0: “☕”, 1: “💻”, 2: “🍷”, 3: “🍫”}
其中键则是可枚举属性,因此 0,1,2,3被记录。
通过for-of循环,我们可以迭代可迭代对象(包括 Array,Map,Set,String,arguments等)。当我们迭代数组时,在每次迭代中,不同属性的值将被分配给变量item, 因此“☕”,“💻”,“🍷”,“🍫”被打印。
80. 输出什么?
const list = [1 + 2, 1 2, 1 / 2]
console.log(list)
复制代码
A: [“1 + 2”, “1
2”, “1 / 2”]
B: [“12”, 2, 0.5]
C: [3, 2, 0.5]
D: [1, 1, 1]
答案
答案: C
数组元素可以包含任何值。 数字,字符串,布尔值,对象,数组,null,undeifned, 以及其他表达式,如日期,函数和计算。
元素将等于返回的值。 1 + 2返回3,1 * 2返回’2,’1 / 2返回0.5。
81. 输出什么?
function sayHi(name) {
return Hi there, ${name}
}

console.log(sayHi())
复制代码
A: Hi there,
B: Hi there, undefined
C: Hi there, null
D: ReferenceError
答案
答案: B
默认情况下,如果不给函数传参,参数的值将为undefined。 上述情况,我们没有给参数name传值。 name等于undefined,并被打印。
在ES6中,我们可以使用默认参数覆盖此默认的undefined值。 例如:
function sayHi(name =“Lydia”){…}
在这种情况下,如果我们没有传递值或者如果我们传递undefined,name总是等于字符串Lydia
82. 输出什么?
var status = “😎”

setTimeout(() => {
const status = “😍”

const data = {
status: “🥑”,
getStatus() {
return this.status
}
}

console.log(data.getStatus())
console.log(data.getStatus.call(this))
}, 0)
复制代码
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时,会打印“😎”。
83. 输出什么?
const person = {
name: “Lydia”,
age: 21
}

let city = person.city
city = “Amsterdam”

console.log(person)
复制代码
A: { name: “Lydia”, age: 21 }
B: { name: “Lydia”, age: 21, city: “Amsterdam” }
C: { name: “Lydia”, age: 21, city: undefined }
D: “Amsterdam”
答案
答案: A
我们将变量city设置为等于person对象上名为city的属性的值。 这个对象上没有名为city的属性,因此变量city的值为undefined。
请注意,我们没有引用person对象本身,只是将变量city设置为等于person对象上city属性的当前值。
然后,我们将city设置为等于字符串“Amsterdam”。 这不会更改person对象:没有对该对象的引用。
因此打印person对象时,会返回未修改的对象。
84. 输出什么?
function checkAge(age) {
if (age < 18) {
const message = “Sorry, you’re too young.”
} else {
const message = “Yay! You’re old enough!”
}

return message
}

console.log(checkAge(21))
复制代码
A: “Sorry, you’re too young.”
B: “Yay! You’re old enough!”
C: ReferenceError
D: undefined
答案
答案: C
const和let声明的变量是具有块级作用域的,块是大括号({})之间的任何东西, 即上述情况if / else语句的花括号。 由于块级作用域,我们无法在声明的块之外引用变量,因此抛出ReferenceError。
85. 什么样的信息将被打印?
fetch(‘https://www.website.com/api/user/1‘)
.then(res => res.json())
.then(res => console.log(res))
复制代码
A: fetch方法的结果
B: 第二次调用fetch方法的结果
C: 前一个.then()中回调方法返回的结果
D: 总是undefined
答案
答案: C
第二个.then中res的值等于前一个.then中的回调函数返回的值。 你可以像这样继续链接.then,将值传递给下一个处理程序。
86. 哪个选项是将hasName设置为true的方法,前提是不能将true作为参数传递?
function getName(name) {
const hasName = //
}
复制代码
A: !!name
B: name
C: new Boolean(name)
D: name.length
答案
答案: A
使用逻辑非运算符!,将返回一个布尔值,使用!! name,我们可以确定name的值是真的还是假的。 如果name是真实的,那么!name返回false。 !false返回true。
通过将hasName设置为name,可以将hasName设置为等于传递给getName函数的值,而不是布尔值true。
new Boolean(true)返回一个对象包装器,而不是布尔值本身。
name.length返回传递的参数的长度,而不是布尔值true。
87. 输出什么?
console.log(“I want pizza”[0])
复制代码
A: “””
B: “I”
C: SyntaxError
D: undefined
答案
答案: B
可以使用方括号表示法获取字符串中特定索引的字符,字符串中的第一个字符具有索引0,依此类推。 在这种情况下,我们想要得到索引为0的元素,字符’I’被记录。
请注意,IE7及更低版本不支持此方法。 在这种情况下,应该使用.charAt()
88. 输出什么?
function sum(num1, num2 = num1) {
console.log(num1 + num2)
}

sum(10)
复制代码
A: NaN
B: 20
C: ReferenceError
D: undefined
答案
答案: B
您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。 我们将值10传递给sum函数。 如果sum函数只接收1个参数,则意味着没有传递num2的值,这种情况下,num1的值等于传递的值10。 num2的默认值是num1的值,即10。 num1 + num2返回20。
如果您尝试将默认参数的值设置为后面定义的参数,则可能导致参数的值尚未初始化,从而引发错误。比如:
function test(m = n, n = 2) {
console.log(m, n)
}
test() // Uncaught ReferenceError: Cannot access ‘n’ before initialization
test(3) // 3 2
test(3, 4) // 3 4
复制代码
89. 输出什么?
// module.js
export default () => “Hello world”
export const name = “Lydia”

// index.js
import * as data from “./module”

console.log(data)
复制代码
A: { default: function default(), name: “Lydia” }
B: { default: function default() }
C: { default: “Hello world”, name: “Lydia” }
D: Global object of module.js
答案
答案: A
使用import * as name语法,我们将module.js文件中所有export导入到index.js文件中,并且创建了一个名为data的新对象。 在module.js文件中,有两个导出:默认导出和命名导出。 默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为name的变量,其值为字符串“Lydia”。
data对象具有默认导出的default属性,其他属性具有指定exports的名称及其对应的值。
90. 输出什么?
class Person {
constructor(name) {
this.name = name
}
}

const member = new Person(“John”)
console.log(typeof member)
复制代码
A: “class”
B: “function”
C: “object”
D: “string”
答案
答案: C
类是构造函数的语法糖,如果用构造函数的方式来重写Person类则将是:
function Person() {
this.name = name
}
复制代码
通过new来调用构造函数,将会生成构造函数Person的实例,对实例执行typeof关键字将返回”object”,上述情况打印出”object”。
91. 输出什么?
let newList = [1, 2, 3].push(4)

console.log(newList.push(5))
复制代码
A: [1, 2, 3, 4, 5]
B: [1, 2, 3, 5]
C: [1, 2, 3, 4]
D: Error
答案
答案: D
.push方法返回数组的长度,而不是数组本身! 通过将newList设置为[1,2,3].push(4),实际上newList等于数组的新长度:4。
然后,尝试在newList上使用.push方法。 由于newList是数值4,抛出TypeError。
92. 输出什么?
function giveLydiaPizza() {
return “Here is pizza!”
}

const giveLydiaChocolate = () => “Here’s chocolate… now go hit the gym already.”

console.log(giveLydiaPizza.prototype)
console.log(giveLydiaChocolate.prototype)
复制代码
A: { constructor: …} { constructor: …}
B: {} { constructor: …}
C: { constructor: …} {}
D: { constructor: …} undefined
答案
答案: D
常规函数,例如giveLydiaPizza函数,有一个prototype属性,它是一个带有constructor属性的对象(原型对象)。 然而,箭头函数,例如giveLydiaChocolate函数,没有这个prototype属性。 尝试使用giveLydiaChocolate.prototype访问prototype属性时会返回undefined。
93. 输出什么?
const person = {
name: “Lydia”,
age: 21
}

for (const [x, y] of Object.entries(person)) {
console.log(x, y)
}
复制代码
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。
94. 输出什么?
function getItems(fruitList, …args, favoriteFruit) {
return […fruitList, …args, favoriteFruit]
}

getItems([“banana”, “apple”], “pear”, “orange”)
复制代码
A: [“banana”, “apple”, “pear”, “orange”]
B: [[“banana”, “apple”], “pear”, “orange”]
C: [“banana”, “apple”, [“pear”], “orange”]
D: SyntaxError
答案
答案: D
… args是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。
function getItems(fruitList, favoriteFruit, …args) {
return […fruitList, …args, favoriteFruit]
}

getItems([“banana”, “apple”], “pear”, “orange”)
复制代码
上述例子是有效的,将会返回数组:[ ‘banana’, ‘apple’, ‘orange’, ‘pear’ ]
95. 输出什么?
function nums(a, b) {
if
(a > b)
console.log(‘a is bigger’)
else
console.log(‘b is bigger’)
return
a + b
}

console.log(nums(4, 2))
console.log(nums(1, 2))
复制代码
A: a is bigger, 6 and b is bigger, 3
B: a is bigger, undefined and b is bigger, undefined
C: undefined and undefined
D: SyntaxError
答案
答案: B
在JavaScript中,我们不必显式地编写分号(;),但是JavaScript引擎仍然在语句之后自动添加分号。这称为自动分号插入。例如,一个语句可以是变量,或者像throw、return、break这样的关键字。
在这里,我们在新的一行上写了一个return语句和另一个值a + b。然而,由于它是一个新行,引擎并不知道它实际上是我们想要返回的值。相反,它会在return后面自动添加分号。你可以这样看:
return;
a + b
复制代码
这意味着永远不会到达a + b,因为函数在return关键字之后停止运行。如果没有返回值,就像这里,函数返回undefined。注意,在if/else语句之后没有自动插入!
96. 输出什么?
class Person {
constructor() {
this.name = “Lydia”
}
}

Person = class AnotherPerson {
constructor() {
this.name = “Sarah”
}
}

const member = new Person()
console.log(member.name)
复制代码
A: “Lydia”
B: “Sarah”
C: Error: cannot redeclare Person
D: SyntaxError
答案
答案: B
我们可以将类设置为等于其他类/函数构造函数。 在这种情况下,我们将Person设置为AnotherPerson。 这个构造函数的名字是Sarah,所以新的Person实例member上的name属性是Sarah。
97. 输出什么?
const info = {
[Symbol(‘a’)]: ‘b’
}

console.log(info)
console.log(Object.keys(info))
复制代码
A: {Symbol(‘a’): ‘b’} and [“{Symbol(‘a’)”]
B: {} and []
C: { a: “b” } and [“a”]
D: {Symbol(‘a’): ‘b’} and []
答案
答案: D
Symbol类型是不可枚举的。Object.keys方法返回对象上的所有可枚举的键属性。Symbol类型是不可见的,并返回一个空数组。 记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
这是Symbol的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用2个想要向同一对象添加属性的库时),您还可以隐藏这种方式对象的属性(尽管不完全。你仍然可以使用Object.getOwnPropertySymbols()方法访问 Symbol。
98. 输出什么?
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))
复制代码
A: [1, [2, 3, 4]] and undefined
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函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须在圆括号之间编写它,否则不会返回任何值!下面的函数将返回一个对象:
const getUser = user => ({ name: user.name, age: user.age })
由于在这种情况下不返回任何值,因此该函数返回undefined。
99. 输出什么?
const name = “Lydia”

console.log(name())
复制代码
A: SyntaxError
B: ReferenceError
C: TypeError
D: undefined
答案
答案: C
变量name保存字符串的值,该字符串不是函数,因此无法调用。
当值不是预期类型时,会抛出TypeErrors。 JavaScript期望name是一个函数,因为我们试图调用它。 但它是一个字符串,因此抛出TypeError:name is not a function
当你编写了一些非有效的JavaScript时,会抛出语法错误,例如当你把return这个词写成retrun时。 当JavaScript无法找到您尝试访问的值的引用时,抛出ReferenceErrors。
100. 输出什么?
// 🎉✨ This is my 100th question! ✨🎉

const output = ${[] && 'Im'}possible!<br />You should${'' &&n’t} see a therapist after so much JavaScript lol
复制代码
A: possible! You should see a therapist after so much JavaScript lol
B: Impossible! You should see a therapist after so much JavaScript lol
C: possible! You shouldn’t see a therapist after so much JavaScript lol
D: Impossible! You shouldn’t see a therapist after so much JavaScript lol
答案
答案: B
[]是一个真值。 使用&&运算符,如果左侧值是真值,则返回右侧值。 在这种情况下,左侧值[]是一个真值,所以返回Im。
“”是一个假值。 如果左侧值是假的,则不返回任何内容。 n’t不会被退回。
101.输出什么?
const one = (false || {} || null)
const two = (null || false || “”)
const three = ([] || 0 || true)

console.log(one, two, three)
复制代码
A: false null []
B: null “” true
C: {} “” []
D: null null true
答案
答案: C
使用||运算符,我们可以返回第一个真值。 如果所有值都是假值,则返回最后一个值。
(false || {} || null):空对象{}是一个真值。 这是第一个(也是唯一的)真值,它将被返回。one等于{}。
(null || false ||“”):所有值都是假值。 这意味着返回传递的值””。 two等于””。
([] || 0 ||“”):空数组[]是一个真值。 这是第一个返回的真值。 three等于[]。

  1. 依次输出什么?
    const myPromise = () => Promise.resolve(‘I have resolved!’)

function firstFunction() {
myPromise().then(res => console.log(res))
console.log(‘second’)
}

async function secondFunction() {
console.log(await myPromise())
console.log(‘second’)
}

firstFunction()
secondFunction()
复制代码
A: I have resolved!, second and I have resolved!, second
B: second, I have resolved! and second, I have resolved!
C: I have resolved!, second and second, I have resolved!
D: second, I have resolved! and I have resolved!, second
答案
答案: D
有了promise,我们通常会说:当我想要调用某个方法,但是由于它可能需要一段时间,因此暂时将它放在一边。只有当某个值被resolved/rejected,并且执行栈为空时才使用这个值。
我们可以在async函数中通过.then和await关键字获得该值。 尽管我们可以通过.then和await获得promise的价值,但是它们的工作方式有所不同。
在 firstFunction中,当运行到myPromise方法时我们将其放在一边,即promise进入微任务队列,其他后面的代码(console.log(‘second’))照常运行,因此second被打印出,firstFunction方法到此执行完毕,执行栈中宏任务队列被清空,此时开始执行微任务队列中的任务,I have resolved被打印出。
在secondFunction方法中,我们通过await关键字,暂停了后面代码的执行,直到异步函数的值被解析才开始后面代码的执行。这意味着,它会等着直到myPromise 以值I have resolved被解决之后,下一行second才开始执行。
103. 输出什么?
const set = new Set()

set.add(1)
set.add(“Lydia”)
set.add({ name: “Lydia” })

for (let item of set) {
console.log(item + 2)
}
复制代码
A: 3, NaN, NaN
B: 3, 7, NaN
C: 3, Lydia2, [Object object]2
D: “12”, Lydia2, [Object object]2
答案
答案: C
“+”运算符不仅用于数值相加,还可以使用它来连接字符串。 每当JavaScript引擎发现一个或多个值不是数字时,就会将数字强制转化为字符串。
第一个是数字1, 1 + 2返回数字3。
但是,第二个是字符串Lydia。 Lydia是字符串,2是数字:2被强制转换为字符串。 Lydia和2被连接起来,产生字符Lydia2。
{name:“Lydia”}是一个对象。 数字和对象都不是字符串,因此将二者都字符串化。 每当我们对常规对象进行字符串化时,它就会变成“[Object object]”。
104. 结果是什么?
Promise.resolve(5)
复制代码
A: 5
B: Promise {: 5}
C: Promise {: 5}
D: Error
答案
答案: C
我们可以将我们想要的任何类型的值传递Promise.resolve,无论是否promise。 该方法本身返回带有已解析值的Promise。 如果您传递常规函数,它将是具有常规值的已解决promise。 如果你通过了promise,它将是一个已经resolved的且带有传的值的promise。
上述情况,我们传了数字5,因此返回一个resolved状态的promise,resolve值为5
105. 输出什么?
function compareMembers(person1, person2 = person) {
if (person1 !== person2) {
console.log(“Not the same!”)
} else {
console.log(“They are the same!”)
}
}

const person = { name: “Lydia” }

compareMembers(person)
复制代码
A: Not the same!
B: They are the same!
C: ReferenceError
D: SyntaxError
答案
答案: B
对象通过引用传递。 当我们检查对象的严格相等性(===)时,我们正在比较它们的引用。
我们将person2的默认值设置为person对象,并将person对象作为person1的值传递。
这意味着两个值都引用内存中的同一位置,因此它们是相等的。
运行“ else”语句中的代码块,并记录They are the same! 。
106. 输出什么?
const colorConfig = {
red: true,
blue: false,
green: true,
black: true,
yellow: false,
}

const colors = [“pink”, “red”, “blue”]

console.log(colorConfig.colors[1])
复制代码
A: true
B: false
C: undefined
D: TypeError
答案
答案: D
在JavaScript中,我们有两种访问对象属性的方法:括号表示法或点表示法。 在此示例中,我们使用点表示法(colorConfig.colors)代替括号表示法(colorConfig [“ colors”])。
使用点表示法,JavaScript会尝试使用该确切名称在对象上查找属性。 在此示例中,JavaScript尝试在colorconfig对象上找到名为colors的属性。 没有名为“colors”的属性,因此返回“undefined”。 然后,我们尝试使用[1]访问第一个元素的值。 我们无法对未定义的值执行此操作,因此会抛出Cannot read property ‘1’ of undefined。
JavaScript解释(或取消装箱)语句。 当我们使用方括号表示法时,它会看到第一个左方括号[并一直进行下去,直到找到右方括号]。 只有这样,它才会评估该语句。 如果我们使用了colorConfig [colors [1]],它将返回colorConfig对象上red属性的值。
107. 输出什么?
console.log(‘❤️’ === ‘❤️’)
复制代码
A: true
B: false
答案
答案: A
在内部,表情符号是unicode。 心表情符号的unicode是U+2764 U+FE0F。 对于相同的表情符号,它们总是相同的,因此我们正在将两个相等的字符串相互比较,这将返回true。
108. 哪些方法修改了原数组?
const emojis = [‘✨’, ‘🥑’, ‘😍’]

emojis.map(x => x + ‘✨’)
emojis.filter(x => x !== ‘🥑’)
emojis.find(x => x !== ‘🥑’)
emojis.reduce((acc, cur) => acc + ‘✨’)
emojis.slice(1, 2, ‘✨’)
emojis.splice(1, 2, ‘✨’)
复制代码
A: All of them
B: map reduce slice splice
C: map slice splice
D: splice
答案
答案: D
使用splice方法,我们通过删除,替换或添加元素来修改原始数组。 上述情况,我们从索引1中删除了2个元素(删除了’🥑’和’😍’),并添加了✨emoji表情。
map,filter和slice返回一个新数组,find返回一个元素,而reduce返回一个减小的值。
109. 输出什么?
const food = [‘🍕’, ‘🍫’, ‘🥑’, ‘🍔’]
const info = { favoriteFood: food[0] }

info.favoriteFood = ‘🍝’

console.log(food)
复制代码
A: [‘🍕’, ‘🍫’, ‘🥑’, ‘🍔’]
B: [‘🍝’, ‘🍫’, ‘🥑’, ‘🍔’]
C: [‘🍝’, ‘🍕’, ‘🍫’, ‘🥑’, ‘🍔’]
D: ReferenceError
答案
答案: A
我们将info对象上的favoriteFood属性的值设置为披萨表情符号“🍕”的字符串。字符串是原始数据类型。在JavaScript中,原始数据类型通过值起作用
在这种情况下,我们将info对象上的favoriteFood属性的值设置为等于food数组中的第一个元素的值,字符串为披萨表情符号(’🍕’ )。字符串是原始数据类型,并且通过值进行交互,我们更改info对象上favoriteFood属性的值。 food数组没有改变,因为favoriteFood的值只是该数组中第一个元素的值的复制,并且与该元素上的元素没有相同的内存引用食物[0]。当我们记录食物时,它仍然是原始数组[‘🍕’,’🍫’,’🥑’,’🍔’]。
110. 这个函数干了什么?
JSON.parse()
复制代码
A: Parses JSON to a JavaScript value
B: Parses a JavaScript object to JSON
C: Parses any JavaScript value to JSON
D: Parses JSON to a JavaScript object only
答案
答案: A
使用JSON.parse()方法,我们可以将JSON字符串解析为JavaScript值。
// 将数字字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
const jsonNumber = JSON.stringify(4) // ‘4’
JSON.parse(jsonNumber) // 4

// 将数组值字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
const jsonArray = JSON.stringify([1, 2, 3]) // ‘[1, 2, 3]’
JSON.parse(jsonArray) // [1, 2, 3]

// 将对象字符串化为有效的JSON,然后将JSON字符串解析为JavaScript值:
const jsonArray = JSON.stringify({ name: “Lydia” }) // ‘{“name”:”Lydia”}’
JSON.parse(jsonArray) // { name: ‘Lydia’ }
复制代码
111. 输出什么?
let name = ‘Lydia’

function getName() {
console.log(name)
let name = ‘Sarah’
}

getName()
复制代码
A: Lydia
B: Sarah
C: undefined
D: ReferenceError
答案
答案: D
每个函数都有其自己的执行上下文。 getName函数首先在其自身的上下文(范围)内查找,以查看其是否包含我们尝试访问的变量name。 上述情况,getName函数包含其自己的name变量:我们用let关键字和Sarah的值声明变量name。
带有let关键字(和const)的变量被提升,但是与var不同,它不会被初始化。 在我们声明(初始化)它们之前,无法访问它们。 这称为“暂时性死区”。 当我们尝试在声明变量之前访问变量时,JavaScript会抛出ReferenceError: Cannot access ‘name’ before initialization。
如果我们不在getName函数中声明name变量,则javascript引擎会查看原型练。会找到其外部作用域有一个名为name的变量,其值为Lydia。 在这种情况下,它将打印Lydia:
let name = ‘Lydia’

function getName() {
console.log(name)
}

getName() // Lydia
复制代码
112. 输出什么?
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)
复制代码
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
复制代码
在函数 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
复制代码
113. 输出什么?
console.log(${(x => x)('I love')} to program)
复制代码
A: I love to program
B: undefined to program
C: ${(x => x)(‘I love’) to program
D: TypeError
答案
答案: A
带有模板字面量的表达式首先被执行。相当于字符串会包含表达式,这个立即执行函数 (x => x)(‘I love’) 返回的值. 我们向箭头函数 x => x 传递 ‘I love’ 作为参数。x 等价于返回的 ‘I love’。这就是结果 I love to program。
114. 将会发生什么?
let config = {
alert: setInterval(() => {
console.log(‘Alert!’)
}, 1000)
}
config = null
复制代码
A: setInterval 的回调不会被调用
B: setInterval 的回调被调用一次
C: setInterval 的回调仍然会被每秒钟调用
D: 我们从没调用过 config.alert(), config 为 null
答案
答案: C
一般情况下当我们将对象赋值为 null, 那些对象会被进行 垃圾回收(garbage collected) 因为已经没有对这些对象的引用了。然而,setInterval的参数是一个箭头函数(所以上下文绑定到对象 config 了),回调函数仍然保留着对 config的引用。只要存在引用,对象就不会被垃圾回收。因为没有被垃圾回收,setInterval 的回调每1000ms (1s)会被调用一次。
115. 哪一个方法会返回 ‘Hello world!’ ?
const myMap = new Map()
const myFunc = () => ‘greeting’
myMap.set(myFunc, ‘Hello world!’)
//1
myMap.get(‘greeting’)
//2
myMap.get(myFunc)
//3
myMap.get(() => ‘greeting’)
复制代码
A: 1
B: 2
C: 2 and 3
D: All of them
答案
答案: B
当通过 set 方法添加一个键值对,一个传递给 set方法的参数将会是键名,第二个参数将会是值。在这个case里,键名为 函数 () => ‘greeting’,值为’Hello world’。 myMap 现在就是 { () => ‘greeting’ => ‘Hello world!’ }。
1 是错的,因为键名不是 ‘greeting’ 而是 () => ‘greeting’。 3 是错的,因为我们给get 方法传递了一个新的函数。对象受 引用 影响。函数也是对象,因此两个函数严格上并不等价,尽管他们相同:他们有两个不同的内存引用地址。
116. 输出什么?
const person = {
name: “Lydia”,
age: 21
}
const changeAge = (x = { …person }) => x.age += 1
const changeAgeAndName = (x = { …person }) => {
x.age += 1
x.name = “Sarah”
}
changeAge(person)
changeAgeAndName()
console.log(person)
复制代码
A: {name: “Sarah”, age: 22}
B: {name: “Sarah”, age: 23}
C: {name: “Lydia”, age: 22}
D: {name: “Lydia”, age: 23}
答案
答案: C
函数 changeAge 和函数 changeAgeAndName 有着不同的参数,定义一个 新 生成的对象 { …person }。这个对象有着所有 person 对象 中 k/v 值的副本。
首项, 我们调用 changeAge 函数并传递 person 对象作为它的参数。这个函数对 age 属性进行加一操作。person 现在是 { name: “Lydia”, age: 22 }。
然后,我们调用函数 changeAgeAndName ,然而我们没有传递参数。取而代之,x 的值等价 new 生成的对象: { …person }。因为它是一个新生成的对象,它并不会对对象 person 造成任何副作用。person 仍然等价于 { name: “Lydia”, age: 22 }。
117. 下面那个选项将会返回 6?
function sumValues(x, y, z) {
return x + y + z;
}
复制代码
A: sumValues([…1, 2, 3])
B: sumValues([…[1, 2, 3]])
C: sumValues(…[1, 2, 3])
D: sumValues([1, 2, 3])
答案
答案: C
通过展开操作符 …,我们可以 暂开 单个可迭代的元素。函数 sumValues function 接收三个参数: x, y 和 z。…[1, 2, 3] 的执行结果为 1, 2, 3,将会传递给函数 sumValues。
118. 输出什么?
let num = 1;
const list = [“🥳”, “🤠”, “🥰”, “🤪”];
console.log(list[(num += 1)]);
复制代码
A: 🤠
B: 🥰
C: SyntaxError
D: ReferenceError
答案
答案: B
通过 += 操作符,我们对值 num 进行加 1 操作。 num 有初始值 1,因此 1 + 1 的执行结果为 2。数组 list 的第二项为 🥰,console.log(list[2]) 输出 🥰.
119. 输出什么?
const person = {
firstName: “Lydia”,
lastName: “Hallie”,
pet: {
name: “Mara”,
breed: “Dutch Tulip Hound”
},
getFullName() {
return ${this.firstName} ${this.lastName};
}
};
console.log(person.pet?.name);
console.log(person.pet?.family?.name);
console.log(person.getFullName?.());
console.log(member.getLastName?.());
复制代码
A: undefined undefined undefined undefined
B: Mara undefined Lydia Hallie undefined
C: Mara null Lydia Hallie null
D: null ReferenceError null ReferenceError
答案
答案: B
通过 ES10 或 TS3.7+可选链操作符 ?.,我们不再需要显式检测更深层的嵌套值是否有效。如果我们尝试获取 undefined 或 null 的值 (nullish),表达将会短路并返回 undefined. person.pet?.name: person 有一个名为 pet 的属性: person.pet 不是 nullish。它有个名为 name 的属性,并返回字符串 Mara。 person.pet?.family?.name: person 有一个名为 pet 的属性: person.pet 不是 nullish. pet 并没有 一个名为 family 的属性, person.pet.family 是 nullish。表达式返回 undefined。 person.getFullName?.(): person 有一个名为 getFullName 的属性: person.getFullName() 不是 nullish 并可以被调用,返回字符串 Lydia Hallie。 member.getLastName?.(): member is not defined: member.getLastName() is nullish. The expression returns undefined.
120. 输出什么?
const groceries = [“banana”, “apple”, “peanuts”];
if (groceries.indexOf(“banana”)) {
console.log(“We have to buy bananas!”);
} else {
console.log(We don't have to buy bananas!);
}
复制代码
A: We have to buy bananas!
B: We don’t have to buy bananas
C: undefined
D: 1
答案
答案: B
我们传递了一个状态 groceries.indexOf(“banana”) 给if条件语句。groceries.indexOf(“banana”) 返回 0, 一个 falsy 的值。因为if条件语句的状态为 falsy,else 块区内的代码执行,并且 We don’t have to buy bananas! 被输出.
121. 输出什么?
const config = {
languages: [],
set language(lang) {
return this.languages.push(lang);
}
};
console.log(config.language);
复制代码
A: function language(lang) { this.languages.push(lang }
B: 0
C: []
D: undefined
答案
答案: D
方法 language 是一个 setter。Setters 并不保存一个实际值,它们的使命在于 修改 属性。当调用方法 setter, 返回 undefined。
122. 输出什么?
const name = “Lydia Hallie”;
console.log(!typeof name === “object”);
console.log(!typeof name === “string”);
复制代码
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)
123. 输出什么?
const add = x => y => z => {
console.log(x, y, z);
return x + y + z;
};
add(4)(5)(6);
复制代码
A: 4 5 6
B: 6 5 4
C: 4 function function
D: undefined undefined 6
答案
答案: A
函数 add 是一个返回 返回箭头函数的箭头函数 的箭头函数(still with me?)。第一个函数接收一个值为 4 的参数 x。我们调用第二个函数,它接收一个值为 5 的参数 y。然后我们调用第三个函数,它接收一个值为 6 的参数 z。当我们尝试在最后一个箭头函数中获取 x, y 和 z 的值,JS 引擎根据作用域链去找 x 和 y 的值。得到 4 5 6.
124. 输出什么?
async function
range(start, end) {
for (let i = start; i <= end; i++) {
yield Promise.resolve(i);
}
}
(async () => {
const gen = range(1, 3);
for await (const item of gen) {
console.log(item);
}
})();
复制代码
A: Promise {1} Promise {2} Promise {3}
B: Promise {} Promise {} Promise {}
C: 1 2 3
D: undefined undefined undefined
答案
答案: C
我们给 函数range 传递: Promise{1}, Promise{2}, Promise{3},Generator 函数 range 返回一个全是 async object promise 数组。我们将 async object 赋值给变量 gen,之后我们使用for await … of 进行循环遍历。我们将返回的 Promise 实例赋值给 item: 第一个返回 Promise{1}, 第二个返回 Promise{2},之后是 Promise{3}。因为我们正 awaiting item 的值,resolved 状态的 promsie,promise数组的resolved 值 以此为: 1,2,3.
125. 输出什么?
const myFunc = ({ x, y, z }) => {
console.log(x, y, z);
};
myFunc(1, 2, 3);
复制代码
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.
126. 输出什么?
function getFine(speed, amount) {
const formattedSpeed = new Intl.NumberFormat({
‘en-US’,
{ style: ‘unit’, unit: ‘mile-per-hour’ }
}).format(speed)
const formattedAmount = new Intl.NumberFormat({
‘en-US’,
{ style: ‘currency’, currency: ‘USD’ }
}).format(amount)
return The driver drove ${formattedSpeed} and has to pay ${formattedAmount}
}
console.log(getFine(130, 300))
复制代码
A: The driver drove 130 and has to pay 300
B: The driver drove 130 mph and has to pay $300.00
C: The driver drove undefined and has to pay undefined
D: The driver drove 130.00 and has to pay 300.00
答案
答案: B
通过方法 Intl.NumberFormat,我们可以格式化任意区域的数字值。我们对数字值 130 进行 mile-per-hour 作为 unit 的 en-US 区域 格式化,结果为 130 mph。对数字值 300 进行 USD 作为 currentcy 的 en-US 区域格式化,结果为 $300.00.
127. 输出什么?
const spookyItems = [“👻”, “🎃”, “🕸”];
({ item: spookyItems[3] } = { item: “💀” });
console.log(spookyItems);
复制代码
A: [“👻”, “🎃”, “🕸”]
B: [“👻”, “🎃”, “🕸”, “💀”]
C: [“👻”, “🎃”, “🕸”, { item: “💀” }]
D: [“👻”, “🎃”, “🕸”, “[object Object]”]
答案
答案: B
通过解构对象们,我们可以从右手边的对象中拆出值,并且将拆出的值分配给左手边对象同名的属性。在这种情况下,我们将值 “💀” 分配给 spookyItems[3]。相当于我们正在篡改数组 spookyItems,我们给它添加了值 “💀”。当输出 spookyItems 时,结果为 [“👻”, “🎃”, “🕸”, “💀”]。
128. 输出什么?
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));
复制代码
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.
129. 输出什么?
const randomValue = 21;
function getInfo() {
console.log(typeof randomValue);
const randomValue = “Lydia Hallie”;
}
getInfo();
复制代码
A: “number”
B: “string”
C: undefined
D: ReferenceError
答案
答案: D
通过 const 关键字声明的变量在被初始化之前不可被引用:这被称之为 暂时性死去。在函数 getInfo 中, 变量 randomValue 声明在getInfo 的作用域的此法环境中。在想要对 typeof randomValue 进行log之前,变量 randomValue 仍未被初始化: 错误ReferenceError 被抛出! JS引擎并不会根据作用域链网上寻找该变量,因为我们已经在 getInfo 函数中声明了 randomValue 变量。
130. 输出什么?
const myPromise = Promise.resolve(“Woah some cool data”);
(async () => {
try {
console.log(await myPromise);
} catch {
throw new Error(Oops didn't work);
} finally {
console.log(“Oh finally!”);
}
})();
复制代码
A: Woah some cool data
B: Oh finally!
C: Woah some cool data Oh finally!
D: Oops didn’t work Oh finally!
答案
答案: C
在 try 块区,我们打印 myPromise 变量的 awaited 值: “Woah some cool data”。因为try 块区没有错误抛出,catch 块区的代码并不执行。finally 块区的代码 总是 执行,”Oh finally!” 被输出。
131. 输出什么?
const emojis = [“🥑”, [“✨”, “✨”, [“🍕”, “🍕”]]];
console.log(emojis.flat(1));
复制代码
A: [‘🥑’, [‘✨’, ‘✨’, [‘🍕’, ‘🍕’]]]
B: [‘🥑’, ‘✨’, ‘✨’, [‘🍕’, ‘🍕’]]
C: [‘🥑’, [‘✨’, ‘✨’, ‘🍕’, ‘🍕’]]
D: [‘🥑’, ‘✨’, ‘✨’, ‘🍕’, ‘🍕’]
答案
答案: B
通过方法 flat, 我们可以创建一个新的, 已被扁平化的数组。被扁平化的深度取决于我们传递的值。在这个case里,我们传递了值 1 (并不必要,这是默认值),相当于只有第一层的数组才会被连接。即这个 case 里的 [‘🥑’] and [‘✨’, ‘✨’, [‘🍕’, ‘🍕’]]。连接这两个数组得到结果 [‘🥑’, ‘✨’, ‘✨’, [‘🍕’, ‘🍕’]].
132. 输出什么?
class Counter {
constructor() {
this.count = 0;
}
increment() {
this.count++;
}
}
const counterOne = new Counter();
counterOne.increment();
counterOne.increment();
const counterTwo = counterOne;
counterTwo.increment();
console.log(counterOne.count);
复制代码
A: 0
B: 1
C: 2
D: 3
答案
答案: D
counterOne 是类 Counter 的一个实例。类 Counter 包含一个count 属性在它的构造函数里, 和一个 increment 方法。首先,我们通过 counterOne.increment() 调用方法 increment 两次。现在counterOne.count 为 2.
然后,我们创建一个新的变量 counterTwo 并将 counterOne 的引用地址赋值给它。因为对象受引用地址的影响,我们刚刚创建了一个新的对象,其引用地址和 counterOne 的等价。因此它们指向同一块内存地址,任何对其的副作用都会影响 counterTwo。现在 counterTwo.count 为 2。我们调用 counterTwo.increment() 将 count 的值设为 3。
然后,我们打印counterOne 里的count为3.
133. 输出什么?
const myPromise = Promise.resolve(Promise.resolve(“Promise!”));
function funcOne() {
myPromise.then(res => res).then(res => console.log(res));
setTimeout(() => console.log(“Timeout!”, 0));
console.log(“Last line!”);
}
async function funcTwo() {
const res = await myPromise;
console.log(await res);
setTimeout(() => console.log(“Timeout!”, 0));
console.log(“Last line!”);
}
funcOne();
funcTwo();
复制代码
A: Promise! Last line! Promise! Last line! Last line! Promise!
B: Last line! Timeout! Promise! Last line! Timeout! Promise!
C: Promise! Last line! Last line! Promise! Timeout! Timeout!
D: Last line! Promise! Promise! Last line! Timeout! Timeout!
答案
答案: D
首先,我们调用 funcOne。在函数 funcOne 的第一行,我们调用myPromise promise 异步操作。当JS引擎在忙于执行 promise,它继续执行函数 funcOne。下一行 异步操作 setTimeout,其回调函数被 Web API 调用。 (详情请参考我关于event loop的文章.) promise 和 timeout 都是异步操作,函数继续执行当JS引擎忙于执行promise 和 处理 setTimeout 的回调。相当于 Last line! 首先被输出, 因为它不是异步操作。执行完 funcOne 的最后一行,promise 状态转变为 resolved,Promise! 被打印。然而,因为我们调用了 funcTwo(), 调用栈不为空,setTimeout 的回调仍不能入栈。 我们现在处于 funcTwo,先 awaiting myPromise。通过 await 关键字, 我们暂停了函数的执行直到 promise 状态变为 resolved (或 rejected)。然后,我们输出 res 的 awaited 值(因为 promise 本身返回一个 promise)。 接着输出 Promise!。 下一行就是 异步操作 setTimeout,其回调函数被 Web API 调用。 我们执行到函数 funcTwo 的最后一行,输出 Last line!。现在,因为 funcTwo 出栈,调用栈为空。在事件队列中等待的回调函数(() => console.log(“Timeout!”) from funcOne, and () => console.log(“Timeout!”) from funcTwo)以此入栈。第一个回调输出 Timeout!,并出栈。然后,第二个回调输出 Timeout!,并出栈。得到结果 Last line! Promise! Promise! Last line! Timeout! Timeout!
134. 我们怎样才能在 index.js 中调用 sum.js? 中的 sum?
// sum.js
export default function sum(x) {
return x + x;
}
// index.js
import as sum from “./sum”;
复制代码
A: sum(4)
B: sum.sum(4)
C: sum.default(4)
D: 默认导出不用
来导入,只能具名导出
答案
答案: C
使用符号 ,我们引入文件中的所有值,包括默认和具名。如果我们有以下文件:
// info.js
export const name = “Lydia”;
export const age = 21;
export default “I love JavaScript”;
// index.js
import
as info from “./info”;
console.log(info);
复制代码
将会输出以下内容:
{
default: “I love JavaScript”,
name: “Lydia”,
age: 21
}
复制代码
以 sum 为例,相当于以下形式引入值 sum:
{ default: function sum(x) { return x + x } }
复制代码
我们可以通过调用 sum.default 来调用该函数
135. 输出什么?
const handler = {
set: () => console.log(“Added a new property!”),
get: () => console.log(“Accessed a property!”)
};
const person = new Proxy({}, handler);
person.name = “Lydia”;
person.name;
复制代码
A: Added a new property!
B: Accessed a property!
C: Added a new property! Accessed a property!
D: 没有任何输出
答案
答案: C
使用 Proxy 对象,我们可以给一个对象添加自定义行为。在这个 case,我们传递一个包含以下属性的对象 handler : set and get。每当我门 设置 属性值时 set 被调用,每当我们 获取 时 get 被调用。 第一个参数是一个空对象 {},作为 person 的值。对于这个对象,自定义行为被定义在对象 handler。如果我们向对象 person 添加属性,set 将被调用。如果我们获取 person 的属性, get 将被调用。 首先,我们向 proxy 对象(person.name = “Lydia”)添加一个属性 name。set 被调用并输出 “Added a new property!”。 然后,我们获取 proxy 对象的一个属性,对象 handler 的属性 get 被调用。输出 “Accessed a property!”。
136. 以下哪一项会对对象 person 有副作用?
const person = { name: “Lydia Hallie” };
Object.seal(person);
复制代码
A: person.name = “Evan Bacon”
B: person.age = 21
C: delete person.name
D: Object.assign(person, { age: 21 })
答案
答案: A
使用 Object.seal 我们可以防止新属性 被添加,或者存在属性 被移除. 然而,你仍然可以对存在属性进行更改。
137. 以下哪一项会对对象 person 有副作用?
const person = {
name: “Lydia Hallie”,
address: {
street: “100 Main St”
}
};
Object.freeze(person);
复制代码
A: person.name = “Evan Bacon”
B: delete person.address
C: person.address.street = “101 Main St”
D: person.pet = { name: “Mara” }
答案
答案: C
使用方法 Object.freeze 对一个对象进行 冻结。不能对属性进行添加,修改,删除。 然而,它仅 对对象进行 浅 冻结,意味着只有 对象中的 直接 属性被冻结。如果属性是另一个 object,像案例中的 address,address 中的属性没有被冻结,仍然可以被修改。
138. 以下哪一项会对对象 person 有副作用?
const person = {
name: “Lydia Hallie”,
address: {
street: “100 Main St”
}
};
Object.freeze(person);
复制代码
A: person.name = “Evan Bacon”
B: delete person.address
C: person.address.street = “101 Main St”
D: person.pet = { name: “Mara” }
答案
答案: C
使用方法 Object.freeze 对一个对象进行 冻结。不能对属性进行添加,修改,删除。 然而,它仅 对对象进行 浅 冻结,意味着只有 对象中的 直接 属性被冻结。如果属性是另一个 object,像案例中的 address,address 中的属性没有被冻结,仍然可以被修改。
139. 输出什么?
const add = x => x + x;
function myFunc(num = 2, value = add(num)) {
console.log(num, value);
}
myFunc();
myFunc(3);
复制代码
A: 2 4 and 3 6
B: 2 NaN and 3 NaN
C: 2 Error and 3 6
D: 2 4 and 3 Error
答案
答案: A
首先我们不传递任何参数调用 myFunc()。因为我们没有传递参数,num 和 value 获取它们各自的默认值:num 为 2, 而 value 为函数 add 的返回值。对于函数 add,我们传递值为2的 num 作为参数。函数 add 返回 4 作为 value 的值。 然后,我们调用 myFunc(3) 并传递值 3 参数 num 的值。我们没有给 value 传递值。因为我们没有给参数 value 传递值,它获取默认值:函数 add 的返回值。对于函数 add,我们传递值为3的 num给它。函数 add 返回 6 作为 value 的值。
140. 输出什么?
class Counter {
#number = 10
increment() {
this.#number++
}
getNum() {
return this.#number
}
}
const counter = new Counter()
counter.increment()
console.log(counter.#number)
复制代码
A: 10
B: 11
C: undefined
D: SyntaxError
答案
答案: D
在 ES2020 中,通过 # 我们可以给 class 添加私有变量。在 class 的外部我们无法获取该值。当我们尝试输出 counter.#number,语法错误被抛出:我们无法在 class Counter 外部获取它!
141. 选择哪一个?
const teams = [
{ name: “Team 1”, members: [“Paul”, “Lisa”] },
{ name: “Team 2”, members: [“Laura”, “Tim”] }
];
function getMembers(members) {
for (let i = 0; i < members.length; i++) {
yield members[i];
}
}
function
getTeams(teams) {
for (let i = 0; i < teams.length; i++) {
// ✨ SOMETHING IS MISSING HERE ✨
}
}
const obj = getTeams(teams);
obj.next(); // { value: “Paul”, done: false }
obj.next(); // { value: “Lisa”, done: false }
复制代码
A: yield getMembers(teams[i].members)
B: yield getMembers(teams[i].members)
C: return getMembers(teams[i].members)
D: return yield getMembers(teams[i].members)
答案
答案: B
为了遍历 teams 数组中对象的属性 members 中的每一项,我们需要将 teams[i].members 传递给 Generator 函数 getMembers。Generator 函数返回一个 generator 对象。为了遍历这个 generator 对象中的每一项,我们需要使用 yield
. 如果我们没有写 yield,return yield 或者 return,整个 Generator 函数不会第一时间 return 当我们调用 next 方法.
142. 输出什么?
const person = {
name: “Lydia Hallie”,
hobbies: [“coding”]
};
function addHobby(hobby, hobbies = person.hobbies) {
hobbies.push(hobby);
return hobbies;
}
addHobby(“running”, []);
addHobby(“dancing”);
addHobby(“baking”, person.hobbies);
console.log(person.hobbies);
复制代码
A: [“coding”]
B: [“coding”, “dancing”]
C: [“coding”, “dancing”, “baking”]
D: [“coding”, “running”, “dancing”, “baking”]
答案
答案: C
函数 addHobby 接受两个参数,hobby 和有着对象 person 中数组 hobbies 默认值的 hobbies。 首相,我们调用函数 addHobby,并给 hobby 传递 “running” 以及给 hobbies 传递一个空数组。因为我们给 hobbies 传递了空数组,”running” 被添加到这个空数组。 然后,我们调用函数 addHobby,并给 hobby 传递 “dancing”。我们不向 hobbies 传递值,因此它获取其默认值 —— 对象 person 的 属性 hobbies。我们向数组 person.hobbies push dancing。 最后,我们调用函数 addHobby,并向 hobby 传递 值 “bdaking”,并且向 hobbies 传递 person.hobbies。我们向数组 person.hobbies push dancing。 pushing dancing 和 baking 之后,person.hobbies 的值为 [“coding”, “dancing”, “baking”]
143. 输出什么?
class Bird {
constructor() {
console.log(“I’m a bird. 🦢”);
}
}
class Flamingo extends Bird {
constructor() {
console.log(“I’m pink. 🌸”);
super();
}
}
const pet = new Flamingo();
复制代码
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. 🦢”。
144. 哪一个选项会导致报错?
const emojis = [“🎄”, “🎅🏼”, “🎁”, “⭐”];
/ 1 / emojis.push(“🦌”);
/ 2 / emojis.splice(0, 2);
/ 3 / emojis = […emojis, “🥂”];
/ 4 / emojis.length = 0;
复制代码
A: 1
B: 1 and 2
C: 3 and 4
D: 3
答案
答案: D
const 关键字意味着我们不能 重定义 变量中的值,它 仅可读。而然,值本身不可修改。数组 emojis 中的值可被修改,如 push 新的值, 拼接,又或者将数组的长度设置为0。
145. 我们需要向对象 person 添加什么,以致执行 […person] 时获得形如 [“Lydia Hallie”, 21] 的输出?
const person = {
name: “Lydia Hallie”,
age: 21
}
[…person] // [“Lydia Hallie”, 21]
复制代码
A: 不需要,对象默认就是可迭代的
B: Symbol.iterator { for (let x in this) yield this[x] }
C: Symbol.iterator { for (let x in this) yield Object.values(this) }
D: Symbol.iterator { for (let x in this) yield this }
答案
答案: C
对象默认并不是可迭代的。如果迭代规则被定义,则一个对象是可迭代的(An iterable is an iterable if the iterator protocol is present)。我们可以通过添加迭代器symbol [Symbol.iterator] 来定义迭代规则,其返回一个 generator 对象,比如说构建一个 generator 函数
Symbol.iterator {}。如果我们想要返回数组 [“Lydia Hallie”, 21]: yield* Object.values(this),这个 generator 函数一定要 yield 对象 person 的Object.values。
146. 输出什么?
let count = 0;
const nums = [0, 1, 2, 3];

nums.forEach(num => {
if (num) count += 1
})

console.log(count)
复制代码
A: 1
B: 2
C: 3
D: 4
答案
答案: C
forEach循环中的if条件检查num的值是真还是假。 由于nums数组中的第一个数字为0,即:伪造的值,因此if语句的代码块将不会执行。 对于nums数组中的其他3个数字,count只会增加,分别为1、2和3。 由于count被增加了1 3倍,因此count的值是3。
147. 输出什么?
function getFruit(fruits) {
console.log(fruits?.[1]?.[1])
fruits?(console.log(.[1]);)
}

getFruit([[‘🍊’, ‘🍌’], [‘🍍’]])
getFruit()
getFruit([[‘🍍’], [‘🍊’, ‘🍌’]])
复制代码
A: null, undefined, 🍌
B: [], null, 🍌
C: [], [], 🍌
D: undefined, undefined, 🍌
答案
答案: D
“?”允许我们选择访问对象内更深层的嵌套属性。我们正在尝试将子项记录在fruits数组的索引“ 1”上的子数组中的索引“ 1”上。如果fruits数组中的索引1上的子数组不存在,它将简单地返回undefined。如果存在“水果”数组中索引“ 1”上的子数组,但是此子数组在其“ 1”索引上没有任何项,则它还将返回undefined。
首先,我们试图将第二项记录在[[[‘🍊’,’🍌’],[‘🍍’]]]的[‘🍍’]`子数组中。此子数组仅包含一个项目,这意味着索引“ 1”上没有任何项目,并返回“ undefined”。
然后,我们在调用getFruits函数时未传递值作为参数,这意味着默认情况下,fruits的值为undefined。由于我们有条件地链接“水果”的索引“ 1”上的项目,因此它返回“未定义”,因为索引“ 1”上的该项目不存在。
最后,我们尝试将第二项记录在[‘🍍’],[‘🍊’,’🍌’]的[‘🍊’,’🍌’]子数组中。该子数组中索引“ 1”上的项是“🍌”,将其记录下来。
148. 输出什么?
class Calc {
constructor() {
this.count = 0
}

increase() {<br />        this.count ++<br />    }<br />}

const calc = new Calc()
new Calc().increase()

console.log(calc.count)
复制代码
A: 0
B: 1
C: undefined
D: ReferenceError
答案
答案: A
我们将变量calc设置为等于Calc类的新实例。 然后,我们实例化一个新的Calc实例,并对该实例调用increase方法。 由于count属性位于Calc类的构造函数中,因此count属性不会在Calc的原型上共享。 这意味着对于calc所指向的实例,count的值尚未更新,count仍为0。
149. 输出什么?
const user = {
email: “e@mail.com”,
password: “12345”
}

const updateUser = ({ email, password }) => {
if (email) {
Object.assign(user, { email })
}

if (password) {<br />        user.password = password<br />    }

return user<br />}

const updatedUser = updateUser({ email: “new@email.com” })

console.log(updatedUser === user)
复制代码
A: false
B: true
C: TypeError
D: ReferenceError
答案
答案: B
如果将用户的“ email”和“ password”属性的值传递给函数,则“ updateUser”函数将其值更新,此后该函数将返回“ user”对象。 函数“ updateUser”的返回值是“ user”对象,这意味着updatedUser的值是对“ user”指向的同一“ user”对象的引用。 “ updatedUser === user”等于“ true”。
150. 输出什么?
const fruit = [‘🍌’, ‘🍊’, ‘🍎’]

fruit.slice(0, 1)
fruit.splice(0, 1)
fruit.unshift(‘🍇’)
复制代码
A: [‘🍌’, ‘🍊’, ‘🍎’]
B: [‘🍊’, ‘🍎’]
C: [‘🍇’, ‘🍊’, ‘🍎’]
D: [‘🍇’, ‘🍌’, ‘🍊’, ‘🍎’]
答案
答案: C
首先,我们在fruit数组上调用slice方法。 slice方法不会修改原始数组,但会返回从数组中切出的值:香蕉表情符号。 然后,我们在fruit数组上调用splice方法。 拼接方法确实修改了原始数组,这意味着fruit数组现在由[[🍊],’🍎’]组成。 最后,我们在“fruit”数组上调用“ unshift”方法,该方法通过添加提供的值“🍇”作为数组中的第一个元素来修改原始数组。 水果数组现在由“ [“🍇”,“🍊”,“🍎”]组成。
151. 输出什么?
const animals = {};
let dog = { emoji: ‘🐶’ }
let cat = { emoji: ‘🐈’ }

animals[dog] = { …dog, name: “Mara” }
animals[cat] = { …cat, name: “Sara” }

console.log(animals[dog])
复制代码
A: { emoji: “🐶”, name: “Mara” }
B: { emoji: “🐈”, name: “Sara” }
C: undefined
D: ReferenceError
答案
答案: B
对象键将转换为字符串。
由于“ dog”的值是一个对象,因此“ animals [dog]”实际上意味着我们正在创建一个名为““ Object Object””的新属性,该属性等于新对象。 “ animals [“ object Object”]]现在等于{emoji:“🐶”,名称:“ Mara”}。
“ cat”也是一个对象,这意味着“ animals [cat]”实际上意味着我们正在使用新的cat属性覆盖“ animals [“” object Object“”“]]的值。
因为将dog对象转换为字符串结果“ object Object”,所以记录animals [dog]或实际上是“ animals [” object Object“]都会返回{emoji:”🐈“,名称:” Sara”}`。
152. 输出什么?
const user = {
email: “my@email.com”,
updateEmail: email => {
this.email = email
}
}

user.updateEmail(“new@email.com”)
console.log(user.email)
复制代码
A: my@email.com
B: new@email.com
C: undefined
D: ReferenceError
答案
答案: A
updateEmail函数是一个箭头函数,未绑定到user对象。 这意味着关键字“ this”不是在引用“ user”对象,而是在这种情况下引用了全局范围。 用户对象内的电子邮件值不会被更新。 记录“ user.email”的值时,将返回“ my@email.com”的原始值。
153. 输出什么?
const promise1 = Promise.resolve(‘First’)
const promise2 = Promise.resolve(‘Second’)
const promise3 = Promise.reject(‘Third’)
const promise4 = Promise.resolve(‘Fourth’)

const runPromises = async () => {
const res1 = await Promise.all([promise1, promise2])
const res2 = await Promise.all([promise3, promise4])
return [res1, res2]
}

runPromises()
.then(res => console.log(res))
.catch(err => console.log(err))
复制代码
A: [[‘First’, ‘Second’], [‘Fourth’]]
B: [[‘First’, ‘Second’], [‘Third’, ‘Fourth’]]
C: [[‘First’, ‘Second’]]
D: ‘Third’
答案
答案: D
Promise.all方法并行运行传递的promise。 如果一个Promise失败,则Promise.all方法(_rejects)带有rejected的promise的值。 在这种情况下,“ promise3”reject返回了“Third”。 我们正在对runPromises调用进行链接的catch方法中捕获被拒绝的值,以捕获runPromises函数中的所有错误。 因为promise3拒绝了这个值,所以只有Third被记录。
154.当method是下列选项中的那项的时候,将会输出{ name: “Lydia”, age: 22 }?
const keys = [“name”, “age”]
const values = [“Lydia”, 22]

const method = / ?? /
Objectmethod => {
return [keys[i], values[i]]
})) // { name: “Lydia”, age: 22 }
复制代码
A: entries
B: values
C: fromEntries
D: forEach
答案
答案: C
fromEntries方法将二维数组转换为对象。 每个子数组中的第一个元素将是键,每个子数组中的第二个元素将是值。 在这种情况下,我们将在“ keys”数组上进行映射,该数组将返回一个数组,其中第一个元素是当前索引上的键数组的项目,第二个元素是当前索引上的值数组的项目。
这将创建一个包含正确键和值的子数组数组,从而导致`{name:“ Lydia”,age:22}
155. 输出什么?
const createMember = ({ email, address = {}}) => {
const validEmail = /.+\@.+..+/.test(email)
if (!validEmail) throw new Error(“Valid email pls”)

return {<br />        email,<br />        address: address ? address : null<br />    }<br />}

const member = createMember({ email: “my@email.com” })
console.log(member)
复制代码
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的值是默认的空对象{}。 空对象是真实值,这意味着“address? address:null`,条件返回“ true”。 address的值为空对象“ {}”。
156. 输出什么?
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!”)
}
复制代码
A: It’s not a string!
B: Yay it’s a string!
C: TypeError
D: undefined
答案
答案: B
“ if”语句中的条件检查“!typeof randomValue”的值是否等于““ string””。 “!”运算符将值转换为布尔值。 如果值为真,则返回的值为“ false”;如果值为虚假,则返回的值为“ true”。 在这种情况下,“ typeof randomValue”的返回值是真实值““ string””,这意味着“!typeof randomValue”的值是布尔值“ false”。
!! typeof randomValue ===“ string”总是返回false,因为我们实际上是在检查“ false ===” string“。 由于条件返回了“ false”,因此将运行“ else”语句的代码块,并记录“是的,是字符串!”。
Q:什么情况下会碰到跨域问题?有哪些解决方法?
跨域问题是这是浏览器为了安全实施的同源策略导致的,同源策略限制了来自不同源的document、脚本,同源的意思就是两个URL的域名、协议、端口要完全相同。
script标签jsonp跨域、nginx反向代理、node.js中间件代理跨域、后端在头部信息设置安全域名、后端在服务器上设置cors。
Q:如何判断一个变量是对象还是数组?
判断数组和对象分别都有好几种方法,其中用prototype.toString.call()兼容性最好。
function isObjArr(value){
if (Object.prototype.toString.call(value) === “[object Array]”) {
console.log(‘value是数组’);
}else if(Object.prototype.toString.call(value)===’[object Object]’){//这个方法兼容性好一点
console.log(‘value是对象’);
}else{
console.log(‘value不是数组也不是对象’)
}
}
复制代码
ps:千万不能使用typeof来判断对象和数组,因为这两种类型都会返回”object”。
Q:定时器的执行顺序或机制。
这个问题还是挺经常被问到的,有一些会直接问定时器的机制,有一些是通过笔试题的方式问执行顺序然后问我为什么是这样。
长话短说,我们需要记住的是:因为js是单线程的,浏览器遇到setTimeout或者setInterval会先执行完当前的代码块,在此之前会把定时器推入浏览器的待执行事件队列里面,等到浏览器执行完当前代码之后会看一下事件队列里面有没有任务,有的话才执行定时器的代码。 所以即使把定时器的时间设置为0还是会先执行当前的一些代码。
上面是我写的一个栗子,如果还不清楚的话,可以看一下我之前写的这篇Js 的事件循环(Event Loop)机制以及实例讲解
Q:html中title属性和alt属性的区别?
这个问题被问了一次,当时我只记得,alt属性是用于img标签的,当图片失效的时候会出现alt属性里面的内容,title用来标记页面的title,当时面试官问我还有没有其他的区别。我。。。
然后我就找了一篇文章来看,涨了点姿势:
1.alt信息
//1.当图片不输出信息的时候,会显示alt信息 鼠标放上去没有信息,当图片正常读取,不会出现alt信息
2.alt信息
// 2.当图片不输出信息的时候,会显示alt信息 鼠标放上去会出现title信息
//当图片正常输出的时候,不会出现alt信息,鼠标放上去会出现title信息
复制代码
另外还有一些关于title属性的知识:
title属性可以用在除了base,basefont,head,html,meta,param,script和title之外的所有标签
title属性的功能是提示。额外的说明信息和非本质的信息请使用title属性。title属性值可以比alt属性值设置的更长
title属性有一个很好的用途,即为链接添加描述性文字,特别是当连接本身并不是十分清楚的表达了链接的目的。
复制代码
Q:标准盒子模型与IE怪异盒子模型
这个问题主要会出现在笔试题上面,比如:
<div style=”width:100px;height=”100px;border:10px;padding:10px;”>
复制代码
这个盒子在w3c标准盒子模型和IE的怪异盒子模型下面它的宽度分别是多少?
标准盒子模型:总宽度=content100px+border 10px2+padding 10px2 //140px
怪异盒子模型: 总宽度=content60px+ border 10px2+padding 10px2 //100px
复制代码
ps:
box-sizing: content-box || border-box;//css3 box-sizing设置为border-box将使用怪异盒子模型
当怪异盒子的宽度小于border+padding的宽度的时候,content width将变为0,盒子的宽度会被border和padding的总宽度撑开
复制代码
ES5的继承和ES6的继承有什么区别?
ES5的继承时通过prototype或构造函数机制来实现。ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this))。
ES6的继承机制完全不同,实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this
具体的:ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其进行加工。如果不调用super方法,子类得不到this对象。
ps:super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后,才可使用this关键字,否则报错。
Q:CSS3有哪些新增的属性?
这里可以分为边框、背景,渐变,阴影、2D转换 3D转换等之类的来说。
比如:边框(border-radius、border-shadow、border-image)之类的 。
复制代码
具体的可以参见菜鸟教程:链接。类似的镜像问题还有HTML5的新增属性,可以自己谷歌一下。
Q:你知道哪些http状态码?
1xx:1开头的是信息状态码
2xx:2开头的是请求成功
3xx:3开头的是重定向
4xx:4开头的是客户端错误
5xx:5开头的是服务器错误
复制代码
这个问题并不难,在笔试面试都有碰到过,巧的是之前我就总结过一篇类似的文章
Q:如何对一个数组去重?
这个问题出现了好几次,而且很多面试官不满足你只给出一两种方法。
1、Set结构去重。
这是ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
let unique= […new Set(array)];
//es6 Set数据结构类似于数组,成员值是唯一的,有重复的值会自动去重。
//Set内部使用===来判断是否相等,类似’1’和1会两个都保存,NaN和NaN只会保存一个
复制代码
2、遍历,将值添加到新数组,用indexOf()判断值是否存在,已存在就不添加,达到去重效果。
let a = [‘1’,’2’,’3’,1,NaN,NaN,undefined,undefined,null,null, ‘a’,’b’,’b’];
let unique= arr =>{
let newA=[];
arr.forEach(key => {
if( newA.indexOf(key)<0 ){ //遍历newA是否存在key,如果存在key会大于0就跳过push的那一步
newA.push(key);
}
});
return newA;
}
console.log(unique(a)) ;//[“1”, “2”, “3”, 1, NaN, NaN, undefined, null, “a”, “b”]
//ps:这个方法不能分辨NaN,会出现两个NaN。是有问题的,下面那个方法好一点。
复制代码
3、遍历,将数组的值添加到一个对象的属性名里,并给属性赋值,对象不能添加相同属性名,以这个为依据可以实现数组去重,然后用Object.keys(对象)返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组。
let a = [‘1’, ‘2’, ‘3’, 1,NaN,NaN,undefined,undefined,null,null, ‘a’, ‘b’, ‘b’];
const unique = arr => {
var obj = {}
arr.forEach(value => {
obj[value] = 0;//这步新添加一个属性,并赋值,如果不赋值的话,属性会添加不上去
})
return Object.keys(obj);//Object.keys(对象)返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组
}
console.log(unique(a));//[“1”, “2”, “3”, “NaN”, “undefined”, “null”, “a”, “b”]
复制代码
注意:
这个方法会将 number,NaN,undefined,null,变为字符串形式,因为对象的属性名就是一个字符串,根据需求来吧,想想还是Set去重最简单也最有效。
Q:垂直居中有哪些方法?
单行文本的话可以使用height和line-height设置同一高度。
position+margin:设置父元素:position: relative;,子元素height: 100px; position:absolute;top: 50%; margin: -50px 0 0 0;(定高)
position+transform:设置父元素position:relative,子元素:position: absolute;top: 50%;transform: translate(0, -50%);(不定高)
百搭flex布局(ie10+),设置父元素display:flex;align-items: center;(不定高)
类似的还有很多,实际应用中,可能就会使用一两种方法,有兴趣的可以看下这篇文章
Q:翻转一个字符串
这个问题主要在笔试题碰到的多,思路就是先将字符串转成一个数组,然后用数组的reverse()+join()方法。
let str=”hello word”;
let b=[…str].reverse().join(“”);//drow olleh
Q:了解ES6的let和const变量声明吗?跟ES5的var有哪些区别?
let
在同一个作用域里面:var可以重复声明变量,let不能重复声明同一个变量
es5是函数作用域,即一个函数里面才是一个作用域,es6是块级作用域(花括号’{这里面是一个作用域}’),如:if、for花括号里面都是一个作用域。
var有变量提升,可以在变量声明之前使用,let不存在变量提升,在变量之前使用会报错
let 有暂时性死区阮一峰大佬es6入门文档解释如下:

const
const的很多特性跟let的特性一样,都有:不可重复声明,不存在变量提升,有暂时性死区,都是块级作用域。
还有一些跟let命令不一样的地方:const必须在声明的时候赋值,不然就会报错。const声明的常量不能更改。
这里的常量指的是:数值、字符串、布尔值,对于引用类型(数组和对象),const只能保证指针是固定的,至于数组和对象内部有没有改变就是const不能控制的地方
Q:Css的优先级。
这类也通常出现在笔试题中,具体的题目记不太清了。
权重优先级:
!important>style(1000)>id(100)>class(10)
!important是优先级最高的不管权重多少,始终采取important。
如果两个选择器作用在同一元素上,计算权重值,相加。权重高者属性生效。
(笔试题就出现过层叠的class id选择器,作用在同一个标签上,然后问最后哪个css属性生效)
复制代码
有兴趣的可以看一下我写的你对CSS权重真的足够了解吗
Q:继承函数对象的实例方法、原型的继承。
函数对象的继承,在面试的时候,一般出现在笔试题那边,也碰到过几次,下面给出一个答案。
function father(name){//父函数
this.name=name|’koro1’;
this.code=function(){ //父类的实例方法
console.log(this.name+’coding’);
}
};
father.prototype.add=function(food){ //父类的原型方法
console.log(this.name+’eat’+food);
}
function son(name){ //子函数
father.call(this); //将this绑定到子类,绑定父类的实例方法code(原型方法add还未绑定)
this.name=name|| ‘OBKoro1’;
}
son.prototype = new father();//把父类的原型方法绑定到子类,实现继承
var sonVar= new son(‘faker’);//这里也可以传参name
son.prototype.constructor = son;//修复构造函数的指向
console.log(sonVar.code());
console.log(sonVar.add());//可以调用父类的方法了
复制代码
Q:通过reduce函数来实现简单的数组求和,示例数组[3,4,8,0,9];
这是一个简单的笔试题,下面写了两种方法,一种是常见遍历的方法,还有一种是使用eval()方法。
let reduce=(arr)=>{ //第一种常规遍历。
let num=0;
for(let [index,value] of arr.entries()){
num+=value;
}
return num;
}
let reduce=(arr)=>eval(arr.join(“+”)); //第二种
//join() 方法把数组元素放入字符串 上面的栗子: arr.join(“+”)得到字符串:’3+4+8+0+9’;
// eval() 函数计算字符串 ,并执行其中的的 JavaScript 代码
//经提醒:原来有一个reduce()数组求和的方法,把这个方法加上去
let result=[3,4,8,0,9].reduce((total,value)=>{ //这两个参数是默认参数不用设置的
return total+value
});
复制代码
Q:call()和apply()有什么区别?
call()和apply()第一个参数将用作函数内 this 的值,用于改变函数的this指向。call和apply的区别在于call()方法接受逗号分隔的参数作为后面的参数,apply()接受一个参数数组作为后面的参数。
从别的博客那边看到一个简单的记忆方法:从call中的 C 联想到逗号分隔(comma-separated),从apply中的 A 联想到数组(array)。
复制代码
Q:position有哪些值?有什么作用?
static。默认值,不脱离文档流,top,right,bottom,left等属性不生效。
relative。不脱离文档流,依据自身位置进行偏离,当子元素设置absolute,将依据它进行偏离。
absolute。脱离文档流,依据top,right,bottom,left等属性在正常文档流中偏移位置。
fixed。通过浏览器窗口进行定位,出现滚动条的时候,不会随之滚动。
Q:如何实现一个闭包?闭包的作用有哪些?
在一个函数里面嵌套另一个函数,被嵌套的那个函数的作用域是一个闭包。
作用:创建私有变量,减少全局变量,防止变量名污染。可以操作外部作用域的变量,变量不会被浏览器回收,保存变量的值。
Q:请从2017-05-15T09:10:23 Europe/Paris提取出结果[“2017”,”05”,”15”,”09”,”10”,”23”]
这是一道笔试题,正则相关的,看他们要的内容就可以知道,要把所有的数字都提取出来,可以写一个只获取数字的正则表达式。
let str = ‘2017-05-15T09:10:23 Europe/Paris’;
let arr = str.match( /\d{1,}/g);
//match会返回一个数组,
// \d 查找数字
// {1,} 表示至少重复几次
// /g表示全局搜索
复制代码
Q:请描述一下Promise的使用场景,’Promise’它所解决的问题以及现在对于异步操作的解决方案。
这是一道笔试题,这是我当时的回答。
Promise的使用场景:ajax请求,回调函数,复杂操作判断。
Promise是ES6为了解决异步编程所诞生的。
异步操作解决方案:Promise、Generator、定时器(不知道算不算)、还有ES7的async
面试遇到的一些小问题:
这里主要是面试中遇到的一些小的问题,一两句话就可以说清的东西,大家可以稍微看一看。
函数参数变量提升
function aa(val){ //函数参数的变量也会提升
console.log(val);//‘函数传参’
var val=’变量声明’;
console.log(val);//‘变量声明’
}
aa(‘函数传参’);
复制代码
js有哪些方法定义对象?
var obj=new Object();//new 一个对象
var obj={name:”OBKoro1”} //对象字面量写法
复制代码
字符串数字转换运算的问题
console.log(1+’2’+’2’); //122
console.log(+’1’+-‘2’+’2’);//-12
console.log(‘A’+’B’+’2’);//AB2
console.log(‘A’-‘B’+2);//NaN
//两个都是数字才能相加,否则都是以字符串形式拼接。
//相减只能两个都是数字,字符串也会转成数字,如果不能转换,值就为NaN
复制代码
split()、join()的区别?
split()是将字符分割成一个数组,join()将数组转为一个字符串
复制代码
pop()push()unshift()shift()的作用?
pop()删除并返回数组的最后一个元素。
push()可向数组的末尾添加一个或多个元素,并返回新的长度。
unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
复制代码
判断一个数是否是整数
function isIntefer(x){
return x%1===0; //返回布尔
}
复制代码
如何将字符串转为数字,如:12.3b?
var num=parseFloat(‘12.3b’)
复制代码
什么是外边距合并?
当两个垂直外边距相遇时,它们将形成一个外边距,合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
Q:你常用的git/svn 命令行有哪些?行内元素有哪些,块状元素有哪些?css有哪些选择器?
自行谷歌,类似的还有css3新增的属性,H5新增的属性之类的,有空的话,稍微背一背,都碰到过。
复制代码
Vue系列问题:
我在面试过程中很少被问到框架,很多是在笔试题中碰到的,在介绍自己项目的时候,有时候自己会解释这里用到了Vue的什么技术,这个时候面试官可能就会顺着问一问Vue,总的来说问的也不会太深。
以下是笔试真题:
vue-router怎么定义动态路由?怎么获取传过来的动态参数?
定义:path:’a/:value’ 获取:this.$route.params.value。
复制代码
说出至少4中vue当中的指令和它的用法。vue文档显示13个指令
vue如何绑定事件。@click=”事件名”
v-show和v-if指令的共同点和不同点?
1.v-if是删除/添加Dom标签,不占据文档位置,v-show切换css的display属性,控制显示隐藏,还会占据文档位置。
2.v-if会删除dom标签所以v-if性能消耗会高一些,需要频繁切换的话,使用v-show会好一点。
复制代码
的作用的是什么?
<keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
复制代码
列举三个Vue常用的生命周期钩子函数?Vue文档
分别写出webpack打包给服务器和本地开发预览的命令代码:
npm run build npm run dev 我都觉得很弱智。。
复制代码
vue 父子组件是怎么进行传参的?
父组件传参给子组件通过props,子组件传参给父组件是用事件传递的。细节见文档。
复制代码
v-model是用来做什么的,怎么使用。
用来为input输入框或者单选框、select选择框这类的东西做双向绑定的。
使用栗子:
复制代码
vuex的工作流程:
WEB   试题 - 图10
1、在vue组件里面,通过dispatch来触发actions提交修改数据的操作。
2、然后再通过actions的commit来触发mutations来修改数据。
3、mutations接收到commit的请求,就会自动通过Mutate来修改state(数据中心里面的数据状态)里面的数据。
4、最后由store触发每一个调用它的组件的更新
Vuex的作用:项目数据状态的集中管理,复杂组件(如兄弟组件、远房亲戚组件)的数据通信问题。
vue的服务端渲染
vue的双向绑定
正题
第 1 题
if(false){
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
复制代码
查看解析
// 输出
undefined

ReferenceError: b is not defined
复制代码
var不会产生块级作用域,let会产生块级作用域。
伪代码相当于:
var a;
if(false){
a = 1;
let b = 2;
}
console.log(a);
console.log(b);
复制代码

第 2 题
var a = 1;
if(true){
console.log(a);
let a = 2;
}
复制代码
查看解析
// 输出

ReferenceError: Cannot access ‘a’ before initialization

复制代码
let声明的变量不会提升,并且会产生暂存死区。在let声明变量之前访问变量会抛出错误。
第 3 题
var a = {n: 1}
var b = a
a.x = a = {n: 2}

console.log(a.n, b.n);
console.log(a.x, b.x);
复制代码
查看解析
// 输出

2 1

undefined {n: 2}

复制代码

var b = a,此时a和b指向同一个对象。

.运算符比 = 运算符高,先计算a.x,此时
b = {
n:1,
x:undefined
}

相当于给对象添加了x属性。

a.x = a = {n:2};

计算完a.x,再计算 = ,赋值是从右向左,此时a指向一个新对象。
a = {
n:2
}

a.x已经执行过了,此时对象的x属性赋值为a,此时

对象 = {
n:1,
x:{
n:2
}
}

即:
a = {
n:2
}

b = {
n:1,
x:{
n:2
}
}

复制代码
查看运算符优先级
第 4 题
console.log(c);
var c;
function c(a) {
console.log(a);
var a = 3;
function a(){
}
}
c(2);
复制代码
查看解析
// 输出

function c(a){
console.log(a);
var a = 3;
function a(){
}
}

function a(){
}
复制代码
变量提升也有优先级, 函数声明 > arguments > 变量声明
第 5 题
var c = 1;
function c(c) {
console.log(c);
var c = 3;
}
console.log(c);
c(2);
复制代码
查看解析
// 输出

1

TypeError: c is not a function

复制代码
由于函数声明会提升,当函数外的console.log(c)执行时,c已经被赋值为1。因此,执行c(2)时会抛出TypeError,因为1不是函数。
第 6 题
var name = ‘erdong’;
(function () {
if (typeof name === ‘undefined’) {
var name = ‘chen’;
console.log(name);
} else {
console.log(name);
}
})();
复制代码
查看解析
// 输出

chen

复制代码
自执行函数执行时,会先进行变量提升(这里涉及到执行上下文不过多说,一定要搞懂执行上下文),在自执行函数执行时,伪代码为:
var name = ‘erdong’;
(function () {
var name; // 变量name会提升到当前作用域顶部
if (typeof name === ‘undefined’) {
name = ‘chen’
console.log(name)
} else {
console.log(name)
}
})();

复制代码
所以会执行if中的console.log(name)
第 7 题
var a = 10;
function test() {
a = 100;
console.log(a);
console.log(this.a);
var a;
console.log(a);
}
test();
复制代码
查看解析
// 输出

100
10
100
复制代码
test()为函数独立调用,作用域中的this绑定为全局对象window。
test函数执行时,var a被提升到了作用域顶部,因此函数作用域中存在一个变量a。所以在函数中访问的a都是局部作用域中的a。
第 8 题
if (!(‘a’ in window)) {
var a = 1;
}
console.log(a);
复制代码
查看解析
// 输出
undefined
复制代码
由于if后的{}不会产生块级作用域(不包含let,const时),此时的伪代码为:
var a;
if (!(a in window)) {
a = 1;
}
console.log(a);
复制代码
var a相当于window.a。因此!(a in window)转成布尔值为false,不会执行a = 1。所有console.log(a)输出undefined。
第 9 题
var a = 1;

function c(a, b) {
console.log(a);
a = 2;
console.log(a);
}
c();
复制代码
查看解析
//输出

undefined

2
复制代码
跟第4题类似。
第 10 题
var val=1;
var obj={
val:2,
del:function(){
console.log(this);
this.val*=2;
console.log(val);
}
}

obj.del();
复制代码
查看解析
// 输出
obj(指向的值)

1

复制代码
当通过obj.del()调用del函数时,del函数作用域中的this绑定为obj。
在函数作用域中访问val时,由于函数中并没有变量val,因此实际上访问的是全局作用域中的val,即 1。
这里考察的是this的指向,一定要熟练掌握。
第 11 题
var name = “erdong”;
var object = {
name: “chen”,
getNameFunc: function () {
return function () {
return this.name;
}
}
}
console.log(object.getNameFunc()());
复制代码
查看解析
// 输出

erdong
复制代码
object.getNameFunc()(),先执行object.getNameFunc()返回一个函数:
function () {
return this.name;
}
复制代码
返回的函数再执行,相当于
(function () {
return this.name;
})();
复制代码
此时的this绑定为window。因此输出全局变量name的值erdong。
第 12 题
var name = “erdong”;
var object = {
name: “chen”,
getNameFunc: function () {
var that = this;
return function () {
return that.name;
}
}
}
console.log(object.getNameFunc()());

复制代码
查看解析
//输出

chen
复制代码
object.getNameFunc()执行时,此时getNameFunc中的this绑定为object,因此that = object。object.getNameFunc()返回的函数再执行时,产生闭包,因此返回的函数也能访问到外层作用域中的变量that,因此object.name为object.name,即 chen。
第 13 题
(function() {
var a = b = 3;
})();
console.log(typeof a === ‘undefined’);
console.log(typeof b === ‘undefined’);
复制代码
查看解析
// 输出

true

false
复制代码
首先要明白var a = b = 3是怎样执行的,伪代码:
b = 3;
var a = b;
复制代码
因此在自执行函数执行时,b由于未经var等操作符声明,为全局变量。a为函数作用域中的局部变量。因此在外面访问a和b时,其值分别为ReferenceError: a is not defined和3。但是typeof检测未声明的变量不会抛出错误,会返回’undefined’。因此typeof a和typeof b分别返回’undefined’和’number’
第 14 题
var a = 6;
setTimeout(function () {
a = 666;
}, 0)
console.log(a);
复制代码
查看解析
//输出

6
复制代码
setTimeout为宏任务。即使设置延迟为0ms,也是等待同步代码执行完才会执行。因此console.log(a)输出 6
第 15 题
function fn1() {
var a = 2;
function fn2 () {
a++;
console.log(a);
}
return fn2;
}
var f = fn1();
f();
f();
复制代码
查看解析
// 输出

3
4
复制代码
由于fn1函数执行后返回函数fn2,此时产生了闭包。因此fn2中a访问的是fn1作用域中的变量a,因此第一次a++,之后a为3,第二次之后a为4。
第 16 题
var a = (function(foo){
return typeof foo.bar;
})({foo:{bar:1}});

console.log(a);
复制代码
查看解析
//输出

undefined
复制代码
实参foo的值为{foo:{bar:1},因此typeof foo.bar为undefined。
typeof foo.foo.bar为number。
第 17 题
function f(){
return f;
}
console.log(new f() instanceof f);

复制代码
查看解析
//输出

false
复制代码
由于构造函数f的返回值为f。因此new f()的值为f。所以console.log(new f() instanceof f)为console.log(f instanceof f),即 false。
第 18 题
function A () {
}
A.prototype.n = 1;

var b = new A();

A.prototype = {
n: 2,
m: 3
}
var c = new A();

console.log(b.n, b.m);
console.log(c.n, c.m);
复制代码
查看解析
// 输出

1,undefined

2,3

复制代码
var b = new A(); 实例化b时,A的prototype为
A.prototype = {
constructor:A,
n:1
}
复制代码
当访问b.n和b.m时,通过原型链找到A.prototype指向的对象上,即b.n = 1,b.m = undefined。
var c = new A(); 实例化c时,A的prototype为
A.prototype = {
n: 2,
m: 3
}
复制代码
当访问a.n和a.m时,通过原型链找到A.prototype指向的对象上,此时A.prototype重写,因此a.n = 2,b.m = 3。
第 19 题
var F = function(){};
var O = {};
Object.prototype.a = function(){
console.log(‘a’)
}
Function.prototype.b = function(){
console.log(‘b’)
}
var f = new F();

F.a();
F.b();
O.a();
O.b();
复制代码
查看解析
// 输出

a
b
a
TypeError: O.b is not a function

复制代码
F为函数,它也能访问Object原型上的方法,O为对象,不能访问Function原型上的方法。
F的原型链为:
F => F.proto => Function.prototype => Function.prototype.proto => Object.prototype
复制代码
由于Object.prototype在F的原型链上,所以F能访问Object.prototype上的属性和方法。即: F.a(),F.b()能正常访问。
O的原型链为:
O => O.proto => Object.prototype
复制代码
由于Function.prototype不在O的原型链上,因此O不能访问Function.prototype上的方法,即O.b()抛出错误。
如果你对原型和原型链掌握的好,试着理解下面的示例:
console.log(Object instanceof Function);

console.log(Function instanceof Object);

console.log(Function instanceof Function);

复制代码
第 20 题
function Person() {
getAge = function () {
console.log(10)
}
return this;
}

Person.getAge = function () {
console.log(20)
}

Person.prototype.getAge = function () {
console.log(30)
}

var getAge = function () {
console.log(40)
}

function getAge() {
console.log(50)
}

Person.getAge();
getAge();
Person().getAge();
new Person.getAge();
getAge();
new Person().getAge();
复制代码
查看解析
// 输出

20
40
10
20
10
30
复制代码
Person.getAge();此时执行的是Person函数上getAge方法。
Person.getAge = function () {
console.log(20)
}
复制代码
所以输出:20。
getAge();此时执行的是全局中的getAge方法。此时全局getAge方法为:
function () {
console.log(40)
}
复制代码
所以输出:40。
Person().getAge();由于Person()单独执行所以,作用域中的this绑定为window,相当于window.getAge()。同上,执行的都是全局getAge 方法,但是Person执行时,内部执行了
getAge = function () {
console.log(10)
}
复制代码
因此全局getAge方法现在为:
function () {
console.log(10)
}
复制代码
所以输出:10。
new Person.getAge();此时相当于实例化Person.getAge这个函数,伪代码:
var b = Person.getAge;
new b();
复制代码
所以输出:20
getAge();执行全局getAge方法,由于在Person().getAge()执行时把全局getAge方法赋值为:
function () {
console.log(10)
}
复制代码
所以输出:10。
new Person().getAge();此时调用的是Person原型上的getAge方法:
Person.prototype.getAge = function () {
console.log(30)
}
复制代码
所以输出:30。
这里要注意:1.变量提升及提升后再赋值。2.调用构造函数时,带()和不带()的区别。
第 21 题
console.log(false.toString());
console.log([1, 2, 3].toString());
console.log(1.toString());
console.log(5..toString());
复制代码
查看解析
// 输出

‘false’
‘1,2,3’
Uncaught SyntaxError: Invalid or unexpected token
‘5’
复制代码
当执行1.toString();时,由于1.也是有效数字,因此此时变成(1.)toString()。没有用.调用toString方法,因此抛出错误。
正确的应该是:
1..toString();
1 .toString();
(1).toString();
复制代码
第 22 题
console.log(typeof NaN === ‘number’);
复制代码
查看解析
//输出

true
复制代码
NaN为不是数字的数字。虽然它不是数字,但是它也是数字类型。
第 23 题
console.log(1 + “2” + “2”);

console.log(1 + +”2” + “2”);

console.log(1 + -“1” + “2”);

console.log(+”1” + “1” + “2”);

console.log( “A” - “B” + “2”);

console.log( “A” - “B” + 2);
复制代码
查看解析
//输出

‘122’
‘32’
‘02’
‘112’
‘NaN2’
NaN
复制代码
首先要明白两点:
+a,会把a转换为数字。-a会把a转换成数字的负值(如果能转换为数字的话,否则为NaN)。
字符串与任何值相加都是字符串拼接。
console.log(1 + “2” + “2”);简单的字符串拼接,即结果为:’122’。
console.log(1 + +”2” + “2”);这里相当于console.log(1 + 2 + “2”);,然后再字符串拼接。即结果为:’32’。
console.log(1 + -“1” + “2”);这里相当于console.log(1 + -1 + “2”);,然后再字符串拼接。即结果为:’02’。
console.log(+”1” + “1” + “2”);这里相当于console.log(1 + “1” + “2”);,然后再字符串拼接。即结果为:’112’。
console.log( “A” - “B” + “2”);,由于’A’ - ‘B’ = NaN,所以相当于console.log( NaN + “2”);, 然后再字符串拼接。即结果为:’NaN2’。
console.log( “A” - “B” + 2);同上,相当于console.log(NaN + 2),由于NaN+任何值还是NaN,即结果为:NaN。
第 24 题
var a = 666;
console.log(++a);
console.log(a++);
console.log(a);
复制代码
查看解析
// 输出

667
667
668
复制代码
++a先执行+1操作,再执行取值操作。 此时a的值为667。因此输出667。
a++先执行取值操作,再执行+1。 此时输出667,随后a的值变为668。
—a和a—同理。
使用这类运算符时要注意:
1)这里的++、—不能用作于常量。比如
1++; // 抛出错误
复制代码
2)如果a不是数字类型,会首先通过Number(a),将a转换为数字。再执行++等运算。
第 25 题
console.log(typeof a);
function a() {}
var a;
console.log(typeof a);
复制代码
查看解析
// 输出

‘function’
‘function’
复制代码
跟第4题类似。函数会优先于变量声明提前。因此会忽略var a。
第 26 题
var a;
var b = ‘undefined’;
console.log(typeof a);
console.log(typeof b);
console.log(typeof c);

复制代码
查看解析
// 输出
‘undefined’
‘string’
‘undefined’
复制代码
a为声明未赋值,默认为undefined,b的值为字符串’undefined’,c为未定义。
typeof一个未定义的变量时,不会抛出错误,会返回’undefined’。注意typeof返回的都是字符串类型。
第 27 题
var x = 1;
if(function f(){}){
x += typeof f;
}

console.log(x);
复制代码
查看解析
//输出

1undefined
复制代码
function f(){}当做if条件判断,其隐式转换后为true。但是在()中的函数不会声明提升,因此f函数在外部是不存在的。因此typeof f = ‘undefined’,所以x += typeof f,相当于x = x + ‘undefined’为’1undefined’
第 28 题
var str = “123abc”;
console.log(typeof str++);
复制代码
查看解析
// 输出

‘number’
复制代码
在24题解析时提到,使用++运算符时(无论是前置还是后置),如果变量不是数字类型,会首先用Number()转换为数字。因此typeof str++相当于typeof Number(str)++。由于后置的++是先取值后计算,因此相当于typeof Number(“123abc”)。即typeof NaN,所以输出’number’。
第 29 题
console.log(‘b’ + ‘a’ + +’a’+’a’);
复制代码
查看解析
// 输出

baNaNa
复制代码
‘b’ + ‘a’ + +’a’+’a’相当于’ba’ + +’a’+’a’,+’a’会将’a’转换为数字类型,即+’a’ = NaN。所以最终得到’ba’ + NaN +’a’,通过字符串拼接,结果为:baNaNa
第 30 题
var obj = {n: 1};
function fn2(a) {
a.n = 2;
}
fn2(obj);
console.log(obj.n);
复制代码
查看解析
// 输出

2
复制代码
函数传递参数时,如果是基本类型为传递,如果是引用类型,为引用地址的值传递。其实都是值传递。因此形参a和obj引用地址相同,都指向同一个对象。当执行a.n,实际上共同指向的对象修改了,添加了个n属性,因此obj.n为2。
第 31 题
var x = 10;
function fn() {
console.log(x);
}
function show(f) {
var x = 20;
f();
}
show(fn);
复制代码
查看解析
// 输出

10
复制代码
JavaScript采用的是词法作用域,它规定了函数内访问变量时,查找变量是从函数声明的位置向外层作用域中查找,而不是从调用函数的位置开始向上查找。因此fn函数内部访问的x是全局作用域中的x,而不是show函数作用域中的x。
第 32 题
Object.prototype.bar = 1;
var foo = {
goo: undefined
};

console.log(foo.bar);
console.log(‘bar’ in foo);

console.log(foo.hasOwnProperty(‘bar’));
console.log(foo.hasOwnProperty(‘goo’));
复制代码
查看解析
//输出

1
true
false
true

复制代码
in操作符:检测指定对象(右边)原型链上是否有对应的属性值。 hasOwnProperty方法:检测指定对象自身上是否有对应的属性值。两者的区别在于in会查找原型链,而hasOwnProperty不会。
示例中对象foo自身上存在goo属性,而它的原型链上存在bar属性。
通过这个例子要注意如果要判断foo上是否有属性goo,不能简单的通过if(foo.goo){}判断,因为goo的值可能为undefined或者其他可能隐式转换为false的值。
第 33 题
Object.prototype.bar = 1;

var foo = {
moo: 2
};
for(var i in foo) {
console.log(i);
}
复制代码
查看解析
// 输出

‘moo’
‘bar’
复制代码
for…in…遍历对象上除了Symbol以外的可枚举属性,包括原型链上的属性。
第 34 题
function foo1() {
return {
bar: “hello”
};
}
function foo2() {
return
{
bar: “hello”
};
}
console.log(foo1());
console.log(foo2());
复制代码
查看解析
// 输出

{ bar: “hello” }

undefined
复制代码
两个函数唯一区别就是return后面跟的值,一个换行一个不换行。
当我们书写代码时忘记在结尾书写;时,JavaScript解析器会根据一定规则自动补上;。
return
{
bar: “hello”
}
=> 会被解析成
return;
{
bar: “hello”
};
复制代码
因此函数执行后会返回undefined。
第 35 题
console.log((function(){ return typeof arguments; })());
复制代码
查看解析
// 输出

‘object’
复制代码
arguments为类数组,类型为object。因此typeof arguments = ‘object’。
第 36 题
console.log(Boolean(false));
console.log(Boolean(‘0’));
console.log(Boolean(‘’));
console.log(Boolean(NaN));
复制代码
查看解析
//输出

false
true
false
fasle

复制代码
只有下面几种值在转换为布尔值时为false:
+0,-0,NaN,false,’’,null,undefined。

复制代码
除此之外的值在转换为布尔值的时候全部为true。
第 37 题
console.log(Array(3));

console.log(Array(2,3));

复制代码
查看解析
// 输出

[empty × 3]

[2,3]
复制代码
使用Array()创建数组时,要注意传入的值的类型和数量。
第 38 题
console.log(0.1 + 0.2 == 0.3);

复制代码
查看解析
// 输出

false
复制代码
第 39 题
var a=[1, 2, 3];
console.log(a.join());
复制代码
查看解析
//输出

1,2,3
复制代码
join方法如果省略参数,默认以,分隔。
第 40 题
var a = [3];
var b = [1];
console.log(a - b);

复制代码
查看解析

面试题:

1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构?
基本数据类型:Undefined、Null、Boolean、Number、String
值类型:数值、布尔值、null、undefined。
引用类型:对象、数组、函数。
堆栈数据结构:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出!
js数组中提供了以下几个方法可以让我们很方便实现堆栈:
shift:从数组中把第一个元素删除,并返回这个元素的值。
unshift: 在数组的开头添加一个或更多元素,并返回新的长度
push:在数组的中末尾添加元素,并返回新的长度
pop:从数组中把最后一个元素删除,并返回这个元素的值。

2.声明函数作用提升?声明变量和声明函数的提升有什么区别?
(1) 变量声明提升:变量申明在进入执行上下文就完成了。
只要变量在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;

(2) 函数声明提升:执行代码之前会先读取函数声明,意味着可以把函数申明放在调用它的语句后面。
只要函数在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;

(3) 变量or函数声明:函数声明会覆盖变量声明,但不会覆盖变量赋值。
同一个名称标识a,即有变量声明var a,又有函数声明function a() {},不管二者声明的顺序,函数声明会覆盖变量声明,也就是说,此时a的值是声明的函数function a() {}。注意:如果在变量声明的同时初始化a,或是之后对a进行赋值,此时a的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a);

3.判断数据类型?
typeof返回的类型都是字符串形式,可以判断function的类型;在判断除Object类型的对象时比较方便。
判断已知对象类型的方法: instanceof,后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。

4.异步编程?
方法1:回调函数,优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

方法2:时间监听,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以“去耦合”(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

方法3:发布/订阅,性质与“事件监听”类似,但是明显优于后者。

方法4:Promises对象,是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

5.事件流?事件捕获?事件冒泡?
事件流:从页面中接收事件的顺序。也就是说当一个事件产生时,这个事件的传播过程,就是事件流。

IE中的事件流叫事件冒泡;事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)。对于html来说,就是当一个元素产生了一个事件,它会把这个事件传递给它的父元素,父元素接收到了之后,还要继续传递给它的上一级元素,就这样一直传播到document对象(亲测现在的浏览器到window对象,只有IE8及下不这样

事件捕获是不太具体的元素应该更早接受到事件,而最具体的节点应该最后接收到事件。他们的用意是在事件到达目标之前就捕获它;也就是跟冒泡的过程正好相反,以html的click事件为例,document对象(DOM级规范要求从document开始传播,但是现在的浏览器是从window对象开始的)最先接收到click事件的然后事件沿着DOM树依次向下传播,一直传播到事件的实际目标;

6.如何清除一个定时器?
window.clearInterval();
window.clearTimeout();

7.如何添加一个dom对象到body中?innerHTML和innerText区别?
body.appendChild(dom元素);
innerHTML:从对象的起始位置到终止位置的全部内容,包括Html标签。
innerText:从起始位置到终止位置的内容, 但它去除Html标签
分别简述五个window对象、属性

成员对象
window.event window.document window.history
window.screen window.navigator window.external
Window对象的属性如下:
window //窗户自身
window.self //引用本窗户window=window.self
window.name //为窗户命名
window.defaultStatus //设定窗户状态栏信息
window.location //URL地址,配备布置这个属性可以打开新的页面

8.数据持久化技术(ajax)?简述ajax流程
1)客户端产生js的事件
2)创建XMLHttpRequest对象
3)对XMLHttpRequest进行配置
4)通过AJAX引擎发送异步请求
5)服务器端接收请求并且处理请求,返回html或者xml内容
6)XML调用一个callback()处理响应回来的内容
7)页面局部刷新

9.回调函数?
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

10.什么是闭包?* 堆栈溢出有什么区别? 内存泄漏? 那些操作会造成内存泄漏?怎么样防止内存泄漏?
闭包:就是能够读取其他函数内部变量的函数。
堆栈溢出:就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了别的数据。经常会在递归中发生。
内存泄露是指:用动态存储分配函数内存空间,在使用完毕后未释放,导致一直占据该内存单元。直到程序结束。指任何对象在您不再拥有或需要它之后仍然存在。

造成内存泄漏:
setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
防止内存泄露:
1、不要动态绑定事件;
2、不要在动态添加,或者会被动态移除的dom上绑事件,用事件冒泡在父容器监听事件;
3、如果要违反上面的原则,必须提供destroy方法,保证移除dom后事件也被移除,这点可以参考Backbone的源代码,做的比较好;
4、单例化,少创建dom,少绑事件。

11.平时工作中怎么样进行数据交互?如果后台没有提供数据怎么样进行开发?mock数据与后台返回的格式不同意怎么办?
由后台编写接口文档、提供数据接口实、前台通过ajax访问实现数据交互;
在没有数据的情况下寻找后台提供静态数据或者自己定义mock数据;
返回数据不统一时编写映射文件 对数据进行映射。

12 简述ajax执行流程
基本步骤:
var xhr =null;//创建对象
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject(“Microsoft.XMLHTTP”);
}
xhr.open(“方式”,”地址”,”标志位”);//初始化请求
xhr.setRequestHeader(“”,””);//设置http头信息
xhr.onreadystatechange =function(){}//指定回调函数
xhr.send();//发送请求

13.自执行函数?用于什么场景?好处?
自执行函数:1、声明一个匿名函数2、马上调用这个匿名函数。
作用:创建一个独立的作用域。

好处:防止变量弥散到全局,以免各种js库冲突。隔离作用域避免污染,或者截断作用域链,避免闭包造成引用变量无法释放。利用立即执行特性,返回需要的业务函数或对象,避免每次通过条件判断来处理

场景:一般用于框架、插件等场景

14.html和xhtml有什么区别?
HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的标记语言。
1.XHTML 元素必须被正确地嵌套。
2.XHTML 元素必须被关闭。
3.标签名必须用小写字母。
4.空标签也必须被关闭。
5.XHTML 文档必须拥有根元素。

  1. 什么是构造函数?与普通函数有什么区别?
    构造函数:是一种特殊的方法、主要用来创建对象时初始化对象,总与new运算符一起使用,创建对象的语句中构造函数的函数名必须与类名完全相同。
    与普通函数相比只能由new关键字调用,构造函数是类的标示

  2. 通过new创建一个对象的时候,函数内部有哪些改变
    function Person(){}
    Person.prototype.friend = [];
    Person.prototype.name = ‘’;
    // var a = new Person();
    // a.friend[0] = ‘王琦’;
    // a.name = ‘程娇’;
    // var b = new Person();
    // b.friend?
    // b.name?
    1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
    2、属性和方法被加入到 this 引用的对象中。
    3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。

17.事件委托?有什么好处?
(1)利用冒泡的原理,把事件加到父级上,触发执行效果
(2)好处:新添加的元素还会有之前的事件;提高性能。

18.window.onload ==? DOMContentLoaded ?
一般情况下,DOMContentLoaded事件要在window.onload之前执行,当DOM树构建完成的时候就会执行DOMContentLoaded事件,而window.onload是在页面载入完成的时候,才执行,这其中包括图片等元素。大多数时候我们只是想在DOM树构建完成后,绑定事件到元素,我们并不需要图片元素,加上有时候加载外域图片的速度非常缓慢。

19.节点类型?判断当前节点类型?
1. 元素节点
2. 属性节点
3. 文本节点
8. 注释节点
9. 文档节点
通过nodeObject.nodeType判断节点类型:其中,nodeObject 为DOM节点(节点对象)。该属性返回以数字表示的节点类型,例如,元素节点返回 1,属性节点返回 2 。

20.如何合并两个数组?数组删除一个元素?
//三种方法。
(1)var arr1=[1,2,3];
var arr2=[4,5,6];
arr1 = arr1.concat(arr2);
console.log(arr1);
(2)var arr1=[1,2,3];
var arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
(3)var arr1=[1,2,3];
var arr2=[4,5,6];
for (var i=0; i < arr2.length; i++) {
arr1.push( arr2[i] );
}
console.log(arr1);

21.强制转换 显式转换 隐式转换?
//强制类型转换:
Boolean(0) // => false - 零
Boolean(new object()) // => true - 对象
Number(undefined) // => NaN
Number(null) // => 0
String(null) // => “null”
parseInt( )
parseFloat( )
JSON.parse( )
JSON.stringify ( )
隐式类型转换:
在使用算术运算符时,运算符两边的数据类型可以是任意的,比如,一个字符串可以和数字相加。之所以不同的数据类型之间可以做运算,是因为JavaScript引擎在运算之前会悄悄的把他们进行了隐式类型转换的
(例如:x+”” //等价于String(x)
+x //等价于Number(x)
x-0 //同上
!!x //等价于Boolean(x),是双叹号)

显式转换:
如果程序要求一定要将某一类型的数据转换为另一种类型,则可以利用强制类型转换运算符进行转换,这种强制转换过程称为显示转换。
显示转换是你定义让这个值类型转换成你要用的值类型,是底到高的转换。例 int 到float就可以直接转,int i=5,想把他转换成char类型,就用显式转换(char)i

  1. Jq中如何实现多库并存?
    Noconfict 多库共存就是“$ ”符号的冲突。

方法一: 利用jQuery的实用函数$.noConflict();这个函数归还$的名称控制权给另一个库,因此可以在页面上使用其他库。这时,我们可以用”jQuery “这个名称调用jQuery的功能。 $.noConflict();
jQuery(‘#id’).hide();
…..
//或者给jQuery一个别名
var $j=jQuery
$j(‘#id’).hide();
…..

方法二: (function($){})(jQuery)

方法三: jQuery(function($){})
通过传递一个函数作为jQuery的参数,因此把这个函数声明为就绪函数。 我们声明$为就绪函数的参数,因为jQuery总是吧jQuery对象的引用作为第一个参数传递,所以就保证了函数的执行。

23.Jq中get和eq有什么区别?
get() :取得其中一个匹配的元素。num表示取得第几个匹配的元素,get多针对集合元素,返回的是DOM对象组成的数组 eq():获取第N个元素,下标都是从0开始,返回的是一个JQuery对象

24.如何通过原生js 判断一个元素当前是显示还是隐藏状态?
if( document.getElementById(“div”).css(“display”)===’none’)
if( document.getElementById(“div”).css(“display”)===’block’)
$(“#div”).is(“:hidden”); // 判断是否隐藏
$(“#div”).is(“:visible”)

25.Jq如何判断元素显示隐藏?
//第一种:使用CSS属性
var display =$(‘#id’).css(‘display’);
if(display == ‘none’){ alert(“我是隐藏的!”); }
//第二种:使用jquery内置选择器

仅仅是测试所用


if($(“#test”).is(“:hidden”)){ $(“#test”).show(); //如果元素为隐藏,则将它显现 }else{ $(“#test”).hide(); //如果元素为显现,则将其隐藏 }
//第三种:jQuery判断元素是否显示 是否隐藏
var node=$(‘#id’);
if(node.is(‘:hidden’)){  //如果node是隐藏的则显示node元素,否则隐藏
  node.show(); 
}else{
  node.hide();
}

26.移动端上什么是点击穿透?
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了

解决方案:
1、只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’)

2、只用click
下下策,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟

3、tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的

4、pointer-events
比较麻烦且有缺陷, 不建议使用mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现

27.Jq绑定事件的几种方式?on bind ?
jQuery中提供了四种事件监听方式,分别是bind、live、delegate、on,对应的解除监听的函数分别是unbind、die、undelegate、off

Bind( )是使用频率较高的一种,作用就是在选择到的元素上绑定特定事件类型的监听函数;

Live( )可以对后生成的元素也可以绑定相应的事件,处理机制就是把事件绑定在DOM树的根节点上,而不是直接绑定在某个元素上;

Delegate( )采用了事件委托的概念,不是直接为子元素绑定事件,而是为其父元素(或祖先元素也可)绑定事件,当在div内任意元素上点击时,事件会一层层从event target向上冒泡,直至到达你为其绑定事件的元素;

on( )方法可以绑定动态添加到页面元素的事件,on()方法绑定事件可以提升效率;

28.Jq中如何将一个jq对象转化为dom对象?
方法一:
jQuery对象是一个数据对象,可以通过[index]的方法,来得到相应的DOM对象。
如:var $v =$(“#v”) ; //jQuery对象
var v=$v[0]; //DOM对象
alert(v.checked) //检测这个checkbox是否被选中

方法二:
jQuery本身提供,通过.get(index)方法,得到相应的DOM对象
如:var $v=$(“#v”); //jQuery对象
var v=$v.get(0); //DOM对象
alert(v.checked) //检测这个checkbox是否被选中

29.Jq中有几种选择器?分别是什么?
层叠选择器、基本过滤选择器、内容过滤选择器、可视化过滤选择器、属性过滤选择器、子元素过滤选择器、表单元素选择器、表单元素过滤选择器

30.Jq中怎么样编写插件?
//第一种是类级别的插件开发:
//1.1 添加一个新的全局函数 添加一个全局函数,我们只需如下定义:
jQuery.foo = function() {
alert(‘This is a test. This is only a test.’); };

//1.2 增加多个全局函数 添加多个全局函数,可采用如下定义:
jQuery.foo = function() {
alert(‘This is a test. This is only a test.’); };
jQuery.bar = function(param) {
alert(‘This function takes a parameter, which is “‘ + param + ‘“.’); }; 调用时和一个函数的一样的:jQuery.foo();jQuery.bar();或者$.foo();$.bar(‘bar’);
//1.3 使用jQuery.extend(object); 
jQuery.extend({
foo: function() {
alert(‘This is a test. This is only a test.’);
},
bar: function(param) {
alert(‘This function takes a parameter, which is “‘ + param +’”.’);
}
});
//1.4 使用命名空间
// 虽然在jQuery命名空间中,我们禁止使用了大量的javaScript函数名和变量名。
// 但是仍然不可避免某些函数或变量名将于其他jQuery插件冲突,因此我们习惯将一些方法
// 封装到另一个自定义的命名空间。
jQuery.myPlugin = {
foo:function() {
alert(‘This is a test. This is only a test.’);
},
bar:function(param) {
alert(‘This function takes a parameter, which is “‘ + param + ‘“.’);
}
};
//采用命名空间的函数仍然是全局函数,调用时采用的方法:
$.myPlugin.foo();
$.myPlugin.bar(‘baz’);
//通过这个技巧(使用独立的插件名),我们可以避免命名空间内函数的冲突。

//第二种是对象级别的插件开发
//形式1:
(function($){
$.fn.extend({
pluginName:function(opt,callback){
// Our plugin implementation code goes here.
}
})
})(jQuery);

//形式2:
(function($) {
$.fn.pluginName = function() {
// Our plugin implementation code goes here.
};
})(jQuery);
//形参是$,函数定义完成之后,把jQuery这个实参传递进去.立即调用执行。
//这样的好处是,我们在写jQuery插件时,也可以使用$这个别名,而不会与prototype引起冲突

31.$(‘div+.ab’)和$(‘.ab+div’) 哪个效率高?
$(‘div+.ab’)效率高

32.$.map和$.each有什么区别
map()方法主要用来遍历操作数组和对象,会返回一个新的数组。$.map()方法适用于将数组或对象每个项目新阵列映射到一个新数组的函数;
each()主要用于遍历jquery对象,返回的是原来的数组,并不会新创建一个数组。

33.编写一个 getElementsByClassName 封装函数?



34.简述下工作流程
我在之前的公司工作流程大概是这样的:公司定稿会结束以后,会进行简单的技术研讨,然后我们前端会进行先期的技术准备。前端切图人员会进行psd设计稿切图,并且将css文件进行整合。我们主要编写JS部分,其中包括搭建前端框架(大项目),编写js业务和数据持久化操作,我们也会编写js插件并且进行封装方便使用,还有就是编写JS前端组建和JS测试单元,最后将完成的JS部分与切图人员提供的HTML页面进行整合。最后对完成的页面进行功能测试、页面兼容、产品还原。然后对产品进行封存,提交测试。如果出现BUG会返回给我们开发人员进行修改,再提交测试,最后测试成功,进行版本封存。等到程序全部上线的时候进行线上测试。

35.一般使用什么版本控制工具?svn如何对文件加锁
svn加锁目的:为了避免多个人同一时间对同一个文件改动的相互覆盖,版本控制系统就必须有一套冲突处理机制。
svn加锁两种策略:乐观加锁:所有签出的文件都是可读写的,对文件的修改不必获得文件的锁,当你修改完文件签入时,会首先要求你更新本地文件,版本控制系统不会覆盖你的本地修改,而是会让你自己合并冲突后签入。
严格加锁:所有签出的文件都是只读的,任何对文件的修改必须要获得文件的锁,如果其他人没有拥有该文件的锁,那么版本控制系统就会授权给你文件的锁,并将文件设置为可编辑的。
svn两种加锁步骤:乐观加锁:选择你想要获取锁定的文件,然后右键菜单点击TortoiseSVN 选取获取锁定。
严格加锁:在想要采取严格加锁的文件或目录上点击右键,使用TortoiseSVN 属性菜单,点击新建属性,选择需要锁定。
36. git 和 svn的区别?
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。
Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
37. jquery和zepto有什么区别?
1.针对移动端程序,Zepto有一些基本的触摸事件可以用来做触摸屏交互(tap事件、swipe事件),Zepto是不支持IE浏览器的,这不是Zepto的开发者Thomas Fucks在跨浏览器问题上犯了迷糊,而是经过了认真考虑后为了降低文件尺寸而做出的决定,就像jQuery的团队在2.0版中不再支持旧版的IE(6 7 8)一样。因为Zepto使用jQuery句法,所以它在文档中建议把jQuery作为IE上的后备库。那样程序仍能在IE中,而其他浏览器则能享受到Zepto在文件大小上的优势,然而它们两个的API不是完全兼容的,所以使用这种方法时一定要小心,并要做充分的测试。
2.Dom操作的区别:添加id时jQuery不会生效而Zepto会生效。
3.zepto主要用在移动设备上,只支持较新的浏览器,好处是代码量比较小,性能也较好。
jquery主要是兼容性好,可以跑在各种pc,移动上,好处是兼容各种浏览器,缺点是代码量大,同时考虑兼容,性能也不够好。
38. $(function(){})和window.onload 和 $(document).ready(function(){})
window.onload:用于当页面的所有元素,包括外部引用文件,图片等都加载完毕时运行函数内的函数。load方法只能执行一次,如果在js文件里写了多个,只能执行最后一个。

$(document).ready(function(){})和$(function(){})都是用于当页面的标准DOM元素被解析成DOM树后就执行内部函数。这个函数是可以在js文件里多次编写的,对于多人共同编写的js就有很大的优势,因为所有行为函数都会执行到。而且$(document).ready()函数在HMTL结构加载完后就可以执行,不需要等大型文件加载或者不存在的连接等耗时工作完成才执行,效率高。

  1. Jq中 attr 和 prop 有什么区别
    对于HTML元素本身就带有的固有属性,在处理时,使用prop方法。
    对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法。

  2. 简述下 this 和定义属性和方法的时候有什么区别?Prototype?
    this表示当前对象,如果在全局作用范围内使用this,则指代当前页面对象window; 如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用。 我们还可以使用apply和call两个全局方法来改变函数中this的具体指向。

prototype本质上还是一个JavaScript对象。 并且每个函数都有一个默认的prototype属性。

在prototype上定义的属性方法为所有实例共享,所有实例皆引用到同一个对象,单一实例对原型上的属性进行修改,也会影响到所有其他实例。

  1. 什么是预编译语音|预编译处理器?
    Sass是一种CSS预处理器语言,通过编程方式生成CSS代码。因为可编程,所以操控灵活性自由度高,方便实现一些直接编写CSS代码较困难的代码。

同时,因为Sass是生成CSS的语言,所以写出来的Sass文件是不能直接用的,必须经过编译器编译成CSS文件才能使用。

CSS 预处理器是一种语言用来为 CSS 增加一些编程的的特性,无需考虑浏览器的兼容性问题,例如你可以在 CSS 中使用变量、简单的程序逻辑、函数等等在编程语言中的一些基本技巧,可以让你的 CSS 更见简洁,适应性更强,代码更直观等诸多好处。最常用的css预处理器有sass、less css、 stylus。

42.ajax 和 jsonp ?
ajax和jsonp的区别:
相同点:都是请求一个url
不同点:ajax的核心是通过xmlHttpRequest获取内容
jsonp的核心则是动态添加
JSONP 使用简单且兼容性不错,但是只限于 get 请求。
2.CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
3.document.domain
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。

只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域<br />4.webpack配置proxyTable设置开发环境跨域<br />5.nginx代理跨域<br />6.iframe跨域<br />7.postMessage<br />    这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息<br />复制代码<br />说一说前端性能优化方案<br />三个方面来说明前端性能优化<br />一: webapck优化与开启gzip压缩<br />    1.babel-loader用 include 或 exclude 来帮我们避免不必要的转译,不转译node_moudules中的js文件<br />    其次在缓存当前转译的js文件,设置loader: 'babel-loader?cacheDirectory=true'<br />    2.文件采用按需加载等等<br />    3.具体的做法非常简单,只需要你在你的 request headers 中加上这么一句:<br />    accept-encoding:gzip<br />    4.图片优化,采用svg图片或者字体图标<br />    5.浏览器缓存机制,它又分为强缓存和协商缓存<br />二:本地存储——从 Cookie 到 Web Storage、IndexedDB<br />    说明一下SessionStorage和localStorage还有cookie的区别和优缺点<br />三:代码优化<br />    1.事件代理<br />    2.事件的节流和防抖<br />    3.页面的回流和重绘<br />    4.EventLoop事件循环机制<br />    5.代码优化等等

复制代码
说一说SessionStorage和localStorage还有cookie
共同点:都是保存在浏览器端、且同源的
不同点:
1.cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
2.存储大小限制也不同,cookie数据不能超过4K,sessionStorage和localStorage可以达到5M
3.sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;
cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
4.作用域不同
sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在
cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在
复制代码
说一说你用过的css布局
gird布局,layout布局,flex布局,双飞翼,圣杯布局等
复制代码
Promise是什么,解决了什么,之前怎么实现的
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
解决来之前在请求中回调请求产生的回调地狱,使得现在的代码更加合理更加优雅,也更加容易定位查找问题。
复制代码
说说浏览器缓存
缓存可以减少网络 IO 消耗,提高访问速度。浏览器缓存是一种操作简单、效果显著的前端性能优化手段
很多时候,大家倾向于将浏览器缓存简单地理解为“HTTP 缓存”。
但事实上,浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列如下:

Memory Cache
Service Worker Cache
HTTP Cache
Push Cache

缓存它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的情况下,才会走协商缓存
实现强缓存,过去我们一直用 expires。
当服务器返回响应时,在 Response Headers 中将过期时间写入 expires 字段,现在一般使用Cache-Control 两者同时出现使用Cache-Control

协商缓存,Last-Modified 是一个时间戳,如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回:每次请求去判断这个时间戳是否发生变化。
从而去决定你是304读取缓存还是给你返回最新的数据
复制代码
三面
HR谈薪水,问一些公司方面待遇方面,为啥要离职之类的。这个就要看你怎么说来,说得好薪资多点。说不好薪资就要被压一些,重点就是不要说上家公司的坏话,可以谈谈你日后的发展方向,准备专精于某个方面,例如数据可视化之类的


前端开发面试题

前言
只看问题点这里
看全部问题和答案点这里
后面会经常更新题目和答案到github博客
面试有几点需注意:(来源寒冬winter 老师,github:@wintercn)
面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。
题目类型: 理论知识、算法、项目细节、技术视野、开放性题、工作案例。
细节追问: 可以确保问到你开始不懂或面试官开始不懂为止,这样可以大大延展题目的区分度和深度,知道你的实际能力。因为这种知识关联是长时期的学习,临时抱佛脚绝对是记不住的。
回答问题再棒,面试官(可能是你面试职位的直接领导),会考虑我要不要这个人做我的同事?所以态度很重要、除了能做事,还要会做人。(感觉更像是相亲( •̣̣̣̣̣̥́௰•̣̣̣̣̣̥̀ ))
资深的前端开发能把absolute和relative弄混,这样的人不要也罢,因为团队需要的是:你这个人具有可以依靠的才能(靠谱)。
前端开发所需掌握知识点概要:
HTML&CSS:
对Web标准的理解(结构、表现、行为)、浏览器内核、渲染原理、依赖管理、兼容性、CSS语法、层次关系,常用属性、布局、选择器、权重、盒模型、
Hack、CSS预处理器、CSS3、Flexbox、CSS Modules、Document flow、BFC、HTML5(离线 & 存储、Histoy,多媒体、WebGL\SVG\Canvas);
JavaScript:
数据类型、运算、对象、Function、继承、闭包、作用域、事件、Prototype、RegExp、JSON、Ajax、DOM、BOM、
内存泄漏、跨域、异步请求、模板引擎、模块化、Flux、同构、算法、ECMAScript6、Nodejs、HTTP、

其他:
主流MVVM框架(React\Vue\Angular)、Hybrid App\React Native\Weex、TypeScript、RESTFul、WEB安全、前端工程化、依赖管理、性能优化、
重构、团队协作、可维护、易用性、SEO、UED、前端技术选型、快速学习能力等;
作为一名前端工程师,无论工作年头长短都应该掌握的知识点
此条由 王子墨 发表在 攻城师的实验室
1、DOM结构 —— 两个节点之间可能存在哪些关系以及如何在节点之间任意移动。

2、DOM操作 —— 如何添加、移除、移动、复制、创建和查找节点等。

3、事件 —— 如何使用事件,以及IE和标准DOM事件模型之间存在的差别。

4、XMLHttpRequest —— 这是什么、怎样完整地执行一次GET请求、怎样检测错误。

5、严格模式与混杂模式 —— 如何触发这两种模式,区分它们有何意义。

6、盒模型 —— 外边距、内边距和边框之间的关系,及IE8以下版本的浏览器中的盒模型

7、块级元素与行内元素 —— 怎么用CSS控制它们、以及如何合理的使用它们

8、浮动元素 —— 怎么使用它们、它们有什么问题以及怎么解决这些问题。

9、HTML与XHTML —— 二者有什么区别,你觉得应该使用哪一个并说出理由。

10、JSON —— 作用、用途、设计结构。<br />**备注:**<br />根据自己需要选择性阅读,面试题是对理论知识的总结,让自己学会应该如何表达。

资料答案不够正确和全面,欢迎欢迎Star和提交issues。

格式不断修改更新中。

更新记录:
2018-01-14: 公司在招聘前端,使用react技术栈;借此机会更新一波前端框架相关的题目;
2016-10-20: 更新一些已被发现的问题。
2016-03-25: 新增ECMAScript6 相关问题
HTML
Doctype作用?标准模式与兼容模式各有什么区别?
(1)、<!DOCTYPE>声明位于HTML文档中的第一行,处于 标签之前。告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

(2)、标准模式的排版 和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。
HTML5 为什么只需要写 <!DOCTYPE HTML>?
HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照它们应该的方式来运行);

而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。
行内元素有哪些?块级元素有哪些? 空(void)元素有那些?
首先:CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,如div的display默认值为“block”,则为“块级”元素;span默认display属性值为“inline”,是“行内”元素。

(1)行内元素有:a b span img input select strong(强调的语气)
(2)块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p

(3)常见的空元素:


WEB   试题 - 图11
鲜为人知的是:

不同浏览器(版本)、HTML4(5)、CSS2等实际略有差异
参考: http://stackoverflow.com/questions/6867254/browsers-default-css-for-html-elements
页面导入样式时,使用link和@import有什么区别?
(1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS;

(2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;

(3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;

(4)link支持使用js控制DOM去改变样式,而@import不支持;
介绍一下你对浏览器内核的理解?
主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。

JS引擎则:解析和执行javascript来实现网页的动态效果。

最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
常见的浏览器内核有哪些?
Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]
Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]

详细文章:浏览器内核的解析和对比
html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
* HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
绘画 canvas;
用于媒介回放的 video 和 audio 元素;
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
sessionStorage 的数据在浏览器关闭后自动删除;
语意化更好的内容元素,比如 article、footer、header、nav、section;
表单控件,calendar、date、time、email、url、search;
新的技术webworker, websocket, Geolocation;

移除的元素:<br />        纯表现的元素:basefont,big,center,font, s,strike,tt,u;<br />        对可用性产生负面影响的元素:frame,frameset,noframes;
  • 支持HTML5新标签:
    IE8/IE7/IE6支持通过document.createElement方法产生的标签,
    可以利用这一特性让这些浏览器支持HTML5新标签,
    浏览器支持新标签后,还需要添加标签默认的样式。

    当然也可以直接使用成熟的框架、比如html5shim;

  • 如何区分HTML5: DOCTYPE声明\新增的结构元素\功能元素
    简述一下你对HTML语义化的理解?
    用正确的标签做正确的事情。
    html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
    即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
    搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO;
    使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
    HTML5的离线储存怎么使用,工作原理能不能解释一下?
    在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。
    原理:HTML5的离线存储是基于一个新建的.appcache文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。

如何使用:
1、页面头部像下面一样加入一个manifest的属性;
2、在cache.manifest文件的编写离线存储的资源;
CACHE MANIFEST
#v0.11
CACHE:
js/app.js
css/style.css
NETWORK:
resourse/logo.png
FALLBACK:
/ /offline.html
3、在离线状态时,操作window.applicationCache进行需求实现。
详细的使用请参考:
HTML5 离线缓存-manifest简介
有趣的HTML5:离线存储
浏览器是怎么对HTML5的离线储存资源进行管理和加载的呢?
在线的情况下,浏览器发现html头部有manifest属性,它会请求manifest文件,如果是第一次访问app,那么浏览器就会根据manifest文件的内容下载相应的资源并且进行离线存储。如果已经访问过app并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的manifest文件与旧的manifest文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
离线的情况下,浏览器就直接使用离线存储的资源。
详细请参考:有趣的HTML5:离线存储
请描述一下 cookies,sessionStorage 和 localStorage 的区别?
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

有期时间:
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage 数据在当前浏览器窗口关闭后自动删除。
cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
iframe有那些缺点?
iframe会阻塞主页面的Onload事件;
搜索引擎的检索程序无法解读这种页面,不利于SEO;

*iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。

使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript
动态给iframe添加src属性值,这样可以绕开以上两个问题。
Label的作用是什么?是怎么用的?
label标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。



HTML5的form如何关闭自动完成功能?
给不想要提示的 form 或某个 input 设置为 autocomplete=off。
如何实现浏览器内多个标签页之间的通信? (阿里)
WebSocket、SharedWorker;
也可以调用localstorge、cookies等本地存储方式;

localstorge另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,
我们通过监听事件,控制它的值来进行页面信息通信;
注意quirks:Safari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常;
webSocket如何兼容低浏览器?(阿里)
Adobe Flash Socket 、
ActiveX HTMLFile (IE) 、
基于 multipart 编码发送 XHR 、
基于长轮询的 XHR
页面可见性(Page Visibility API) 可以有哪些用途?
通过 visibilityState 的值检测页面当前是否可见,以及打开网页的时间等;
在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放;
如何在页面上实现一个圆形的可点击区域?
1、map+area或者svg
2、border-radius
3、纯js实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等
实现不使用 border 画出1px高的线,在不同浏览器的标准模式与怪异模式下都能保持一致的效果。


网页验证码是干嘛的,是为了解决什么安全问题。
区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水;
有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
title与h1的区别、b与strong的区别、i与em的区别?
title属性没有明确意义只表示是个标题,H1则表示层次明确的标题,对页面信息的抓取也有很大的影响;

strong是标明重点内容,有语气加强的含义,使用阅读设备阅读网络时:会重读,而是展示强调内容。

i内容展示为斜体,em表示强调的文本;

Physical Style Elements — 自然样式标签
b, i, u, s, pre
Semantic Style Elements — 语义样式标签
strong, em, ins, del, code
应该准确使用语义样式标签, 但不能滥用, 如果不能确定时首选使用自然样式标签。
CSS
介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的?
(1)有两种, IE 盒子模型、W3C 盒子模型;
(2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border);
(3)区 别: IE的content部分把 border 和 padding计算了进去;
CSS选择符有哪些?哪些属性可以继承?
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器(

8.属性选择器(a[rel = “external”])
9.伪类选择器(a:hover, li:nth-child)

  • 可继承的样式: font-size font-family color, UL LI DL DD DT;

  • 不可继承的样式:border padding margin width height ;
    CSS优先级算法如何计算?
    优先级就近原则,同权重情况下样式定义最近者为准;
    载入样式以最后载入的定位为准;

    优先级为:
    同权重: 内联样式表(标签内部)> 嵌入样式表(当前文件中)> 外部样式表(外部文件中)。
    !important > id > class > tag
    important 比 内联优先级高
    CSS3新增伪类有那些?
    举例:
    p:first-of-type 选择属于其父元素的首个

    元素的每个

    元素。
    p:last-of-type 选择属于其父元素的最后

    元素的每个

    元素。
    p:only-of-type 选择属于其父元素唯一的

    元素的每个

    元素。
    p:only-child 选择属于其父元素的唯一子元素的每个

    元素。
    p:nth-child(2) 选择属于其父元素的第二个子元素的每个

    元素。

    ::after 在元素之前添加内容,也可以用来做清除浮动。
    ::before 在元素之后添加内容
    :enabled
    :disabled 控制表单控件的禁用状态。
    :checked 单选框或复选框被选中。
    如何居中div?
    水平居中:给div设置一个宽度,然后添加margin:0 auto属性
    div{
    width:200px;
    margin:0 auto;
    }
    让绝对定位的div居中
    div {
    position: absolute;
    width: 300px;
    height: 300px;
    margin: auto;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    background-color: pink; / 方便看效果 /
    }
    水平垂直居中一
    确定容器的宽高 宽500 高 300 的层
    设置层的外边距

    div {
    position: relative; / 相对定位或绝对定位均可 /
    width:500px;
    height:300px;
    top: 50%;
    left: 50%;
    margin: -150px 0 0 -250px; / 外边距为自身宽高的一半 /
    background-color: pink; / 方便看效果 /

    }
    水平垂直居中二
    未知容器的宽高,利用 transform 属性

    div {
    position: absolute; / 相对定位或绝对定位均可 /
    width:500px;
    height:300px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: pink; / 方便看效果 /

    }
    水平垂直居中三
    利用 flex 布局
    实际使用时应考虑兼容性

    .container {
    display: flex;
    align-items: center; / 垂直居中 /
    justify-content: center; / 水平居中 /

    }
    .container div {
    width: 100px;
    height: 100px;
    background-color: pink; / 方便看效果 /
    }
    display有哪些值?说明他们的作用。
    block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
    none 元素不显示,并从文档流中移除。
    inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
    inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。
    list-item 象块类型元素一样显示,并添加样式列表标记。
    table 此元素会作为块级表格来显示。
    inherit 规定应该从父元素继承 display 属性的值。
    position的值relative和absolute定位原点是?
    absolute
    生成绝对定位的元素,相对于值不为 static的第一个父元素进行定位。
    fixed (老IE不支持)
    生成绝对定位的元素,相对于浏览器窗口进行定位。
    relative
    生成相对定位的元素,相对于其正常位置进行定位。
    static
    默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。
    inherit
    规定从父元素继承 position 属性的值。
    CSS3有哪些新特性?
    新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)
    圆角 (border-radius:8px)
    多列布局 (multi-column layout)
    阴影和反射 (Shadow\Reflect)
    文字特效 (text-shadow、)
    文字渲染 (Text-decoration)
    线性渐变 (gradient)
    旋转 (transform)
    缩放,定位,倾斜,动画,多背景
    例如:transform:\scale(0.85,0.90)\ translate(0px,-30px)\ skew(-9deg,0deg)\Animation:
    请解释一下CSS3的Flexbox(弹性盒布局模型),以及适用场景?
    一个用于页面布局的全新CSS3功能,Flexbox可以把列表放在同一个方向(从上到下排列,从左到右),并让列表能延伸到占用可用的空间。
    较为复杂的布局还可以通过嵌套一个伸缩容器(flex container)来实现。
    采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。
    它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。
    常规布局是基于块和内联流方向,而Flex布局是基于flex-flow流可以很方便的用来做局中,能对不同屏幕大小自适应。
    在布局上有了比以前更加灵活的空间。

    具体:http://www.w3cplus.com/css3/flexbox-basics.html
    用纯CSS创建一个三角形的原理是什么?
    把上、左、右三条边隐藏掉(颜色设为 transparent)
    #demo {
    width: 0;
    height: 0;
    border-width: 20px;
    border-style: solid;
    border-color: transparent transparent red transparent;
    }
    一个满屏 品 字布局 如何设计?
    简单的方式:
    上面的div宽100%,
    下面的两个div分别宽50%,
    然后用float或者inline使其不换行即可
    css多列等高如何实现?
    利用padding-bottom|margin-bottom正负值相抵;
    设置父容器设置超出隐藏(overflow:hidden),这样子父容器的高度就还是它里面的列没有设定padding-bottom时的高度,
    当它里面的任 一列高度增加了,则父容器的高度被撑到里面最高那列的高度,
    其他比这列矮的列会用它们的padding-bottom补偿这部分高度差。
    经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用hack的技巧 ?
    * png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.

  • 浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。

  • IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。

    浮动ie产生的双倍距离 #box{ float:left; width:10px; margin:0 0 0 100px;}

    这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 ——display:inline;将其转化为行内属性。(这个符号只有ie6会识别)

    渐进识别的方式,从总体中逐渐排除局部。

    首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。
    接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。

    css
    .bb{
    background-color:red;/所有识别/
    background-color:#00deff\9; /IE6、7、8识别/
    +background-color:#a200ff;/IE6、7识别/
    _background-color:#1e0bd1;/IE6识别/
    }

  • IE下,可以使用获取常规属性的方法来获取自定义属性,
    也可以使用getAttribute()获取自定义属性;
    Firefox下,只能使用getAttribute()获取自定义属性。
    解决方法:统一通过getAttribute()获取自定义属性。

  • IE下,even对象有x,y属性,但是没有pageX,pageY属性;
    Firefox下,event对象有pageX,pageY属性,但是没有x,y属性。

  • 解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。

  • Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,
    可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决。

    超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
    L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
    li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
    行框的排列会受到中间空白(回车\空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔,把字符大小设为0,就没有空格了。
    为什么要初始化CSS样式。
    - 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。

  • 当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。

    最简单的初始化方法: * {padding: 0; margin: 0;} (强烈不建议)

    淘宝的样式初始化代码:
    body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { margin:0; padding:0; }
    body, button, input, select, textarea { font:12px/1.5tahoma, arial, \5b8b\4f53; }
    h1, h2, h3, h4, h5, h6{ font-size:100%; }
    address, cite, dfn, em, var { font-style:normal; }
    code, kbd, pre, samp { font-family:couriernew, courier, monospace; }
    small{ font-size:12px; }
    ul, ol { list-style:none; }
    a { text-decoration:none; }
    a:hover { text-decoration:underline; }
    sup { vertical-align:text-top; }
    sub{ vertical-align:text-bottom; }
    legend { color:#000; }
    fieldset, img { border:0; }
    button, input, select, textarea { font-size:100%; }
    table { border-collapse:collapse; border-spacing:0; }
    absolute的containing block(容器块)计算方式跟正常流有什么不同?
    无论属于哪种,都要先找到其祖先元素中最近的 position 值不为 static 的元素,然后再判断:
    1、若此元素为 inline 元素,则 containing block 为能够包含这个元素生成的第一个和最后一个 inline box 的 padding box (除 margin, border 外的区域) 的最小矩形;
    2、否则,则由这个祖先元素的 padding box 构成。
    如果都找不到,则为 initial containing block。

    补充:
    1. static(默认的)/relative:简单说就是它的父元素的内容框(即去掉padding的部分)
    2. absolute: 向上找最近的定位为absolute/relative的元素
    3. fixed: 它的containing block一律为根元素(html/body),根元素也是initial containing block
    CSS里的visibility属性有个collapse属性值是干嘛用的?在不同浏览器下以后什么区别?
    对于普通元素visibility:collapse;会将元素完全隐藏,不占据页面布局空间,与display:none;表现相同. 如果目标元素为table,visibility:collapse;将table隐藏,但是会占据页面布局空间. 仅在Firefox下起作用,IE会显示元素,Chrome会将元素隐藏,但是占据空间.
    position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?
    如果元素的display为none,那么元素不被渲染,position,float不起作用,如果元素拥有position:absolute;或者position:fixed;属性那么元素将为绝对定位,float不起作用.如果元素float属性不是none,元素会脱离文档流,根据float属性值来显示.有浮动,绝对定位,inline-block属性的元素,margin不会和垂直方向上的其他元素margin折叠.
    对BFC规范(块级格式化上下文:block formatting context)的理解?
    (W3C CSS 2.1 规范中的一个概念,它是一个独立容器,决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。)
    一个页面是由很多个 Box 组成的,元素的类型和 display 属性,决定了这个 Box 的类型。
    不同类型的 Box,会参与不同的 Formatting Context(决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染,也就是说BFC内部的元素和外部的元素不会互相影响。
    css定义的权重
    以下是权重的规则:标签的权重为1,class的权重为10,id的权重为100,以下例子是演示各种定义的权重值:

    /权重为1/
    div{
    }
    /权重为10/
    .class1{
    }
    /权重为100/
    #id1{
    }
    /权重为100+1=101/
    #id1 div{
    }
    /权重为10+1=11/
    .class1 div{
    }
    /权重为10+10+1=21/
    .class1 .class2 div{
    }

    如果权重相同,则最后定义的样式会起作用,但是应该避免这种情况出现
    请解释一下为什么需要清除浮动?清除浮动的方式
    清除浮动是为了清除使用浮动元素产生的影响。浮动的元素,高度会塌陷,而高度的塌陷使我们页面后面的布局不能正常显示。
    1、父级div定义height;
    2、父级div 也一起浮动;
    3、常规的使用一个class;
    .clearfix::before, .clearfix::after {
    content: “ “;
    display: table;
    }
    .clearfix::after {
    clear: both;
    }
    .clearfix {
    *zoom: 1;
    }

    4、SASS编译的时候,浮动元素的父级div定义伪类:after
    &::after,&::before{
    content: “ “;
    visibility: hidden;
    display: block;
    height: 0;
    clear: both;
    }

    解析原理:
    1) display:block 使生成的元素以块级元素显示,占满剩余空间;
    2) height:0 避免生成内容破坏原有布局的高度。
    3) visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;
    4)通过 content:”.”生成内容作为最后一个元素,至于content里面是点还是其他都是可以的,例如oocss里面就有经典的 content:”.”,有些版本可能content 里面内容为空,一丝冰凉是不推荐这样做的,firefox直到7.0 content:”” 仍然会产生额外的空隙;
    5)zoom:1 触发IE hasLayout。

    通过分析发现,除了clear:both用来闭合浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0。
    什么是外边距合并?
    外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。
    合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
    w3school介绍网址: http://www.w3school.com.cn/css/css_margin_collapsing.asp
    zoom:1的清除浮动原理?
    清除浮动,触发hasLayout;
    Zoom属性是IE浏览器的专有属性,它可以设置或检索对象的缩放比例。解决ie下比较奇葩的bug。
    譬如外边距(margin)的重叠,浮动清除,触发ie的haslayout属性等。

    来龙去脉大概如下:
    当设置了zoom的值之后,所设置的元素就会就会扩大或者缩小,高度宽度就会重新计算了,这里一旦改变zoom值时其实也会发生重新渲染,运用这个原理,也就解决了ie下子元素浮动时候父元素不随着自动扩大的问题。

    Zoom属是IE浏览器的专有属性,火狐和老版本的webkit核心的浏览器都不支持这个属性。然而,zoom现在已经被逐步标准化,出现在 CSS 3.0 规范草案中。

    目前非ie由于不支持这个属性,它们又是通过什么属性来实现元素的缩放呢?
    可以通过css3里面的动画属性scale进行缩放。
    移动端的布局用过媒体查询吗?
    假设你现在正用一台显示设备来阅读这篇文章,同时你也想把它投影到屏幕上,或者打印出来, 而显示设备、屏幕投影和打印等这些媒介都有自己的特点,CSS就是为文档提供在不同媒介上展示的适配方法
    当媒体查询为真时,相关的样式表或样式规则会按照正常的级联规被应用。 当媒体查询返回假, 标签上带有媒体查询的样式表 仍将被下载 (只不过不会被应用)。
    包含了一个媒体类型和至少一个使用 宽度、高度和颜色等媒体属性来限制样式表范围的表达式。 CSS3加入的媒体查询使得无需修改内容便可以使样式应用于某些特定的设备范围。

    使用 CSS 预处理器吗?喜欢那个?
    SASS (SASS、LESS没有本质区别,只因为团队前端都是用的SASS)
    CSS优化、提高性能的方法有哪些?
    关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分);
    如果规则拥有 ID 选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了);
    提取项目的通用公有样式,增强可复用性,按模块编写组件;增强项目的协同开发性、可维护性和可扩展性;
    使用预处理工具或构建工具(gulp对css进行语法检查、自动补前缀、打包压缩、自动优雅降级);
    浏览器是怎样解析CSS选择器的?
    样式系统从关键选择器开始匹配,然后左移查找规则选择器的祖先元素。
    只要选择器的子树一直在工作,样式系统就会持续左移,直到和规则匹配,或者是因为不匹配而放弃该规则。
    在网页中的应该使用奇数还是偶数的字体?为什么呢?
    margin和padding分别适合什么场景使用?
    margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。
    margin用于布局分开元素使元素与元素互不相干;
    padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段
    抽离样式模块怎么写,说出思路,有无实践经验?[阿里航旅的面试题]
    元素竖向的百分比设定是相对于容器的高度吗?
    全屏滚动的原理是什么?用到了CSS的那些属性?
    什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的IE?
    视差滚动效果,如何给每页做不同的动画?(回到顶部,向下滑动要再次出现,和只出现一次分别怎么做?)
    ::before 和 :after中双冒号和单冒号 有什么区别?解释一下这2个伪元素的作用。
    单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。(伪元素由双冒号和伪元素名称组成)
    双冒号是在当前规范中引入的,用于区分伪类和伪元素。不过浏览器需要同时支持旧的已经存在的伪元素写法,
    比如:first-line、:first-letter、:before、:after等,
    而新的在CSS3中引入的伪元素则不允许再支持旧的单冒号的写法。

    想让插入的内容出现在其它内容前,使用::before,否者,使用::after;
    在代码顺序上,::after生成的内容也比::before生成的内容靠后。
    如果按堆栈视角,::after生成的内容会在::before生成的内容之上
    如何修改chrome记住密码后自动填充表单的黄色背景 ?
    input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill {
    background-color: rgb(250, 255, 189); / #FAFFBD; /
    background-image: none;
    color: rgb(0, 0, 0);
    }
    你对line-height是如何理解的?
    设置元素浮动后,该元素的display值是多少?
    自动变成了 display:block
    怎么让Chrome支持小于12px 的文字?
    1、用图片:如果是内容固定不变情况下,使用将小于12px文字内容切出做图片,这样不影响兼容也不影响美观。
    2、使用12px及12px以上字体大小:为了兼容各大主流浏览器,建议设计美工图时候设置大于或等于12px的字体大小,如果是接单的这个时候就需要给客户讲解小于12px浏览器不兼容等事宜。
    3、继续使用小于12px字体大小样式设置:如果不考虑chrome可以不用考虑兼容,同时在设置小于12px对象设置-webkit-text-size-adjust:none,做到最大兼容考虑。
    4、使用12px以上字体:为了兼容、为了代码更简单 从新考虑权重下兼容性。
    让页面里的字体变清晰,变细用CSS怎么做?
    -webkit-font-smoothing: antialiased;
    font-style属性可以让它赋值为“oblique” oblique是什么意思?
    倾斜的字体样式
    position:fixed;在android下无效怎么处理?
    fixed的元素是相对整个页面固定位置的,你在屏幕上滑动只是在移动这个所谓的viewport,
    原来的网页还好好的在那,fixed的内容也没有变过位置,
    所以说并不是iOS不支持fixed,只是fixed的元素不是相对手机屏幕固定的。

    如果需要手动写动画,你认为最小时间间隔是多久,为什么?(阿里)
    多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms
    display:inline-block 什么时候会显示间隙?(携程)
    移除空格、使用margin负值、使用font-size:0、letter-spacing、word-spacing
    overflow: scroll时不能平滑滚动的问题怎么处理?
    有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度。
    png、jpg、gif 这些图片格式解释一下,分别什么时候用。有没有了解过webp?
    什么是Cookie 隔离?(或者说:请求资源的时候不要让它带cookie怎么做)
    如果静态文件都放在主域名下,那静态文件请求的时候都带有的cookie的数据提交给server的,非常浪费流量,
    所以不如隔离开。

    因为cookie有域的限制,因此不能跨域提交请求,故使用非主要域名的时候,请求头中就不会带有cookie数据,
    这样可以降低请求头的大小,降低请求时间,从而达到降低整体请求延时的目的。

    同时这种方式不会将cookie传入Web Server,也减少了Web Server对cookie的处理分析环节,
    提高了webserver的http请求的解析速度。
    style标签写在body后与body前有什么区别?
    什么是CSS 预处理器 / 后处理器?
    - 预处理器例如:LESS、Sass、Stylus,用来预编译Sass或less,增强了css代码的复用性,
    还有层级、mixin、变量、循环、函数等,具有很方便的UI组件模块化开发能力,极大的提高工作效率。

  • 后处理器例如:PostCSS,通常被视为在完成的样式表中根据CSS规范处理CSS,让其更有效;目前最常做的
    是给CSS属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。
    rem布局的优缺点
    JavaScript
    介绍js的基本数据类型。
    Undefined、Null、Boolean、Number、String、
    ECMAScript 2015 新增:Symbol(创建后独一无二且不可变的数据类型 )
    介绍js有哪些内置对象?
    Object 是 JavaScript 中所有对象的父对象

    数据封装类对象:Object、Array、Boolean、Number 和 String
    其他对象:Function、Arguments、Math、Date、RegExp、Error

    参考:http://www.ibm.com/developerworks/cn/web/wa-objectsinjs-v1b/index.html
    说几条写JavaScript的基本规范?
    1.不要在同一行声明多个变量。
    2.请使用 ===/!==来比较true/false或者数值
    3.使用对象字面量替代new Array这种形式
    4.不要使用全局函数。
    5.Switch语句必须带有default分支
    6.函数不应该有时候有返回值,有时候没有返回值。
    7.For循环必须使用大括号
    8.If语句必须使用大括号
    9.for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污染。
    JavaScript原型,原型链 ? 有什么特点?
    每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
    如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
    于是就这样一直找下去,也就是我们平时所说的原型链的概念。
    关系:instance.constructor.prototype = instance.proto

    特点:
    JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,
就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。
function Func(){}
Func.prototype.name = “Sean”;
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();//现在可以参考var person = Object.create(oldObject);
console.log(person.getInfo());//它拥有了Func的属性和方法
//“Sean”
console.log(Func.prototype);
// Func { name=”Sean”, getInfo=function()}
JavaScript有几种类型的值?,你能画一下他们的内存图吗?
栈:原始数据类型(Undefined,Null,Boolean,Number、String)
堆:引用数据类型(对象、数组和函数)

两种类型的区别是:存储位置不同;
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

如何将字符串转化为数字,例如’12.3b’?
parseFloat(‘12.3b’);
正则表达式,’12.3b’.match(/(\d)+(.)?(\d)+/g)[0] 1, 但是这个不太靠谱,提供一种思路而已。
如何将浮点数点左边的数每三位添加一个逗号,如12000000.11转化为『12,000,000.11』?
function commafy(num){
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+.)/g, function($1, $2){
return $2 + ‘,’;
});
}
如何实现数组的随机排序?
方法一:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort1(arr){
for(var i = 0,len = arr.length;i < len; i++ ){
var rand = parseInt(Math.random()
len);
var temp = arr[rand];
arr[rand] = arr[i];
arr[i] = temp;
}
return arr;
}
console.log(randSort1(arr));

方法二:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort2(arr){
var mixedArray = [];
while(arr.length > 0){
var randomIndex = parseInt(Math.random()*arr.length);
mixedArray.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return mixedArray;
}
console.log(randSort2(arr));

方法三:
var arr = [1,2,3,4,5,6,7,8,9,10];
arr.sort(function(){
return Math.random() - 0.5;
})
console.log(arr);
Javascript如何实现继承?
1、构造继承
2、原型继承
3、实例继承
4、拷贝继承

原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式。

function Parent(){
this.name = ‘wang’;
}

 function Child(){<br />         this.age = 28;<br />     }<br />     Child.prototype = new Parent();//继承了Parent,通过原型

 var demo = new Child();<br />     alert(demo.age);<br />     alert(demo.name);//得到被继承的属性<br />JavaScript继承的几种实现方式?<br />参考:[构造函数的继承](http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html),[非构造函数的继承](http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html);<br />javascript创建对象的几种方式?<br /> javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用。

1、对象字面量的方式

 person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};

2、用function来模拟无参的构造函数

 function Person(){}<br />     var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class<br />     person.name="Mark";<br />     person.age="25";<br />     person.work=function(){<br />     alert(person.name+" hello...");<br />     }<br />     person.work();

3、用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)

 function Pet(name,age,hobby){<br />        this.name=name;//this作用域:当前对象<br />        this.age=age;<br />        this.hobby=hobby;<br />        this.eat=function(){<br />           alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员");<br />        }<br />     }<br />     var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象<br />     maidou.eat();//调用eat方法

4、用工厂方式来创建(内置对象)

  var wcDog =new Object();<br />      wcDog.name="旺财";<br />      wcDog.age=3;<br />      wcDog.work=function(){<br />        alert("我是"+wcDog.name+",汪汪汪......");<br />      }<br />      wcDog.work();

5、用原型方式来创建

 function Dog(){

  }<br />      Dog.prototype.name="旺财";<br />      Dog.prototype.eat=function(){<br />      alert(this.name+"是个吃货");<br />      }<br />      var wangcai =new Dog();<br />      wangcai.eat();

5、用混合方式来创建

 function Car(name,price){<br />       this.name=name;<br />       this.price=price;<br />     }<br />      Car.prototype.sell=function(){<br />        alert("我是"+this.name+",我现在卖"+this.price+"万元");<br />       }<br />     var camry =new Car("凯美瑞",27);<br />     camry.sell();<br />Javascript作用链域?<br /> 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节。<br /> 当需要从局部函数查找某一属性或方法时,如果当前作用域没有找到,就会上溯到上层作用域查找,<br /> 直至全局函数,这种组织形式就是作用域链。<br />谈谈This对象的理解。<br />this总是指向函数的直接调用者(而非间接调用者);<br />如果有new关键字,this指向new出来的那个对象;<br />在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window;<br />eval是做什么的?<br /> 它的功能是把对应的字符串解析成JS代码并运行;<br /> 应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。<br /> 由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')');<br />什么是window对象? 什么是document对象?<br /> window对象是指浏览器打开的窗口。<br /> document对象是Documentd对象(HTML 文档对象)的一个只读引用,window对象的一个属性。<br />null,undefined 的区别?<br /> null         表示一个对象是“没有值”的值,也就是值为“空”;<br /> undefined     表示一个变量声明了没有初始化(赋值);

undefined不是一个有效的JSON,而null是;
undefined的类型(typeof)是undefined;
null的类型(typeof)是object;

Javascript将未赋值的变量默认值设为undefined;
Javascript从来不会将变量设为null。它是用来让程序员表明某个用var声明的变量时没有值的。

typeof undefined
//“undefined”
undefined :是一个表示”无”的原始值或者说表示”缺少值”,就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined;
例如变量被声明了,但没有赋值时,就等于undefined

typeof null
//“object”
null : 是一个对象(空对象, 没有任何属性和方法);
例如作为函数的参数,表示该函数的参数不是对象;

注意:
在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined
null == undefined // true
null === undefined // false

再来一个例子:

 null<br />     Q:有张三这个人么?<br />     A:有!<br />     Q:张三有房子么?<br />     A:没有!

 undefined<br />     Q:有张三这个人么?<br />     A:有!<br />     Q: 张三有多少岁?<br />     A: 不知道(没有被告诉)<br />参考阅读:[undefined与null的区别](http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html)<br />写一个通用的事件侦听器函数。<br />     // event(事件)工具集,来源:github.com/markyun<br />     markyun.Event = {<br />         // 页面加载完成后<br />         readyEvent : function(fn) {<br />             if (fn==null) {<br />                 fn=document;<br />             }<br />             var oldonload = window.onload;<br />             if (typeof window.onload != 'function') {<br />                 window.onload = fn;<br />             } else {<br />                 window.onload = function() {<br />                     oldonload();<br />                     fn();<br />                 };<br />             }<br />         },<br />         // 视能力分别使用dom0||dom2||IE方式 来绑定事件<br />         // 参数: 操作的元素,事件名称 ,事件处理程序<br />         addEvent : function(element, type, handler) {<br />             if (element.addEventListener) {<br />                 //事件类型、需要执行的函数、是否捕捉<br />                 element.addEventListener(type, handler, false);<br />             } else if (element.attachEvent) {<br />                 element.attachEvent('on' + type, function() {<br />                     handler.call(element);<br />                 });<br />             } else {<br />                 element['on' + type] = handler;<br />             }<br />         },<br />         // 移除事件<br />         removeEvent : function(element, type, handler) {<br />             if (element.removeEventListener) {<br />                 element.removeEventListener(type, handler, false);<br />             } else if (element.datachEvent) {<br />                 element.detachEvent('on' + type, handler);<br />             } else {<br />                 element['on' + type] = null;<br />             }<br />         },<br />         // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)<br />         stopPropagation : function(ev) {<br />             if (ev.stopPropagation) {<br />                 ev.stopPropagation();<br />             } else {<br />                 ev.cancelBubble = true;<br />             }<br />         },<br />         // 取消事件的默认行为<br />         preventDefault : function(event) {<br />             if (event.preventDefault) {<br />                 event.preventDefault();<br />             } else {<br />                 event.returnValue = false;<br />             }<br />         },<br />         // 获取事件目标<br />         getTarget : function(event) {<br />             return event.target || event.srcElement;<br />         },<br />         // 获取event对象的引用,取到事件的所有信息,确保随时能使用event;<br />         getEvent : function(e) {<br />             var ev = e || window.event;<br />             if (!ev) {<br />                 var c = this.getEvent.caller;<br />                 while (c) {<br />                     ev = c.arguments[0];<br />                     if (ev && Event == ev.constructor) {<br />                         break;<br />                     }<br />                     c = c.caller;<br />                 }<br />             }<br />             return ev;<br />         }<br />     };<br />["1", "2", "3"].map(parseInt) 答案是多少?<br /> parseInt() 函数能解析一个字符串,并返回一个整数,需要两个参数 (val, radix),<br /> 其中 radix 表示要解析的数字的基数。【该值介于 2 ~ 36 之间,并且字符串中的数字不能大于radix才能正确返回数字结果值】;<br /> 但此处 map 传了 3 个 (element, index, array),我们重写parseInt函数测试一下是否符合上面的规则。

function parseInt(str, radix) {
return str+’-‘+radix;
};
var a=[“1”, “2”, “3”];
a.map(parseInt); // [“1-0”, “2-1”, “3-2”] 不能大于radix

因为二进制里面,没有数字3,导致出现超范围的radix赋值和不合法的进制解析,才会返回NaN
所以[“1”, “2”, “3”].map(parseInt) 答案也就是:[1, NaN, NaN]

详细解析:http://blog.csdn.net/justjavac/article/details/19473199
事件是?IE与火狐的事件机制有什么区别? 如何阻止冒泡?
1. 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为。
2. 事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件;
3. ev.stopPropagation();(旧ie的方法 ev.cancelBubble = true;)
什么是闭包(closure),为什么要用它?
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

闭包的特性:

1.函数内再嵌套函数
2.内部函数可以引用外层的参数和变量
3.参数和变量不会被垃圾回收机制回收

//li节点的onclick事件都能正确的弹出当前被点击的li索引


  • index = 0

  • index = 1

  • index = 2

  • index = 3


执行say667()后,say667()闭包内部变量会存在,而闭包内部函数的内部变量不会存在
使得Javascript的垃圾回收机制GC不会收回say667()所占用的资源
因为say667()的内部函数的执行需要依赖say667()中的变量
这是对闭包作用的非常直白的描述

function say667() {
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() {
alert(num);
}
num++;
return sayAlert;
}

var sayAlert = say667();
sayAlert()//执行结果应该弹出的667
javascript 代码中的”use strict”;是什么意思 ? 使用它区别是什么?
use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,

使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。
默认支持的糟糕特性都会被禁用,比如不能用with,也不能在意外的情况下给全局变量赋值;
全局变量的显示声明,函数必须声明在顶层,不允许在非函数代码块内声明函数,arguments.callee也不允许使用;
消除代码运行的一些不安全之处,保证代码运行的安全,限制函数中的arguments修改,严格模式下的eval函数的行为和非严格模式的也不相同;

提高编译器效率,增加运行速度;
为未来新版本的Javascript标准化做铺垫。
如何判断一个对象是否属于某个类?
使用instanceof (待完善)
if(a instanceof Person){
alert(‘yes’);
}
new操作符具体干了什么呢?
1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。

var obj = {};
obj.proto = Base.prototype;
Base.call(obj);
用原生JavaScript的实现过什么功能吗?
Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
hasOwnProperty

javaScript中hasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。
使用方法:
object.hasOwnProperty(proName)
其中参数object是必选项。一个对象的实例。
proName是必选项。一个属性名称的字符串值。

如果 object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回 true,反之则返回 false。
JSON 的了解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
如:{“age”:”12”, “name”:”back”}

JSON字符串转换为JSON对象:
var obj =eval(‘(‘+ str +’)’);
var obj = str.parseJSON();
var obj = JSON.parse(str);

JSON对象转换为JSON字符串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
[].forEach.call($$(““),function(a){a.style.outline=”1px solid #”+(~~(Math.random()(1<<24))).toString(16)}) 能解释一下这段代码的意思吗?
js延迟加载的方式有哪些?
defer和async、动态创建DOM方式(用得最多)、按需异步载入js
Ajax 是什么? 如何创建一个Ajax?
ajax的全称:Asynchronous Javascript And XML。
异步传输+js+xml。
所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验。

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
(3)设置响应HTTP请求状态变化的函数
(4)发送HTTP请求
(5)获取异步调用返回的数据
(6)使用JavaScript和DOM实现局部刷新
Ajax 解决浏览器缓存问题?
1、在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,”0”)。

2、在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,”no-cache”)。

3、在URL后面加上一个随机数: “fresh=” + Math.random();。
4、在URL后面加上时间戳:”nowtime=” + new Date().getTime();。
5、如果是使用jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录。
同步和异步的区别?
同步的概念应该是来自于OS中关于同步的概念:不同进程为协同完成某项工作而在先后次序上调整(通过阻塞,唤醒等方式).同步强调的是顺序性.谁先谁后.异步则不存在这种顺序性.
同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作。
异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容。
(待完善)
如何解决跨域问题?
jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面
页面编码和被请求的资源编码如果不一致如何处理?
服务器代理转发时,该如何处理cookie?
nginx
模块化开发怎么做?
立即执行函数,不暴露私有成员
var module1 = (function(){
    var _count = 0;
    var m1 = function(){
      //…
    };
    var m2 = function(){
      //…
    };
    return {
      m1 : m1,
      m2 : m2
    };
  })();
(待完善)
AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?
AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMD
CMD 规范在这里:https://github.com/seajs/seajs/issues/242
Asynchronous Module Definition,异步模块定义,所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中。

区别:

 1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.<br />     2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:

// CMD
define(function(require, exports, module) {
var a = require(‘./a’)
a.doSomething()
// 此处略去 100 行
var b = require(‘./b’) // 依赖可以就近书写
b.doSomething()
// …
})

// AMD 默认推荐
define([‘./a’, ‘./b’], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
// …
})
requireJS的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?)
参考:http://annn.me/how-to-realize-cmd-loader/
JS模块加载器的轮子怎么造,也就是如何实现一个模块加载器?
谈一谈你对ECMAScript6的了解?
ECMAScript6 怎么写class么,为什么会出现class这种东西?
异步加载JS的方式有哪些?
(1) defer,只支持IE

(2) async:

(3) 创建script,插入到DOM中,加载完毕后callBack
documen.write和 innerHTML的区别
document.write只能重绘整个页面

innerHTML可以重绘页面的一部分
DOM操作——怎样添加、移除、移动、复制、创建和查找节点?
(1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点
(3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
.call() 和 .apply() 的区别?
例子中用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4);

注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。

 function add(a,b)<br />     {<br />         alert(a+b);<br />     }

 function sub(a,b)<br />     {<br />         alert(a-b);<br />     }

 add.call(sub,3,1);<br />数组和对象有哪些原生方法,列举一下?<br />JS 怎么实现一个类。怎么实例化这个类<br />JavaScript中的作用域与变量声明提升?<br />如何编写高性能的Javascript?<br />那些操作会造成内存泄漏?<br />JQuery的源码看过吗?能不能简单概况一下它的实现原理?<br />jQuery.fn的init方法返回的this指的是什么对象?为什么要返回this?<br />jquery中如何将数组转化为json字符串,然后再转化回来?<br />jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?<br />jquery.extend 与 jquery.fn.extend的区别?<br /> * jquery.extend 为jquery类添加类方法,可以理解为添加静态方法<br /> * jquery.fn.extend:<br />     源码中jquery.fn = jquery.prototype,所以对jquery.fn的扩展,就是为jquery类添加成员函数<br /> 使用:<br /> jquery.extend扩展,需要通过jquery类来调用,而jquery.fn.extend扩展,所有jquery实例都可以直接调用。<br />jQuery 的队列是如何实现的?队列可以用在哪些地方?<br />谈一下Jquery中的bind(),live(),delegate(),on()的区别?<br />JQuery一个对象可以同时绑定多个事件,这是如何实现的?<br />是否知道自定义事件。jQuery里的fire函数是什么意思,什么时候用?<br />jQuery 是通过哪个方法和 Sizzle 选择器结合的?(jQuery.fn.find()进入Sizzle)<br />针对 jQuery性能的优化方法?<br />Jquery与jQuery UI 有啥区别?<br /> *jQuery是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等。

*jQuery UI则是在jQuery的基础上,利用jQuery的扩展性,设计的插件。
提供了一些常用的界面元素,诸如对话框、拖动行为、改变大小行为等等
JQuery的源码看过吗?能不能简单说一下它的实现原理?
jquery 中如何将数组转化为json字符串,然后再转化回来?
jQuery中没有提供这个功能,所以你需要先编写两个jQuery的扩展:
$.fn.stringifyArray = function(array) {
return JSON.stringify(array)
}

$.fn.parseArray = function(array) {<br />        return JSON.parse(array)<br />    }

然后调用:<br />    $("").stringifyArray(array)<br />jQuery和Zepto的区别?各自的使用场景?<br />针对 jQuery 的优化方法?<br /> *基于Class的选择性的性能相对于Id选择器开销很大,因为需遍历所有DOM元素。

*频繁操作的DOM,先缓存起来再操作。用Jquery的链式调用更好。
比如:var str=$(“a”).attr(“href”);

*for (var i = size; i < arr.length; i++) {}
for 循环每一次循环都查找了数组 (arr) 的.length 属性,在开始循环的时候设置一个变量来存储这个数字,可以让循环跑得更快:
for (var i = size, length = arr.length; i < length; i++) {}
Zepto的点透问题如何解决?
jQueryUI如何自定义组件?
需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应。给出你的技术实现方案?
如何判断当前脚本运行在浏览器还是node环境中?(阿里)
this === window ? ‘browser’ : ‘node’;

通过判断Global对象是否为window,如果不为window,当前脚本没有运行在浏览器中
移动端最小触控区域是多大?
jQuery 的 slideUp动画 ,如果目标元素是被外部事件驱动, 当鼠标快速地连续触发外部元素事件, 动画会滞后的反复执行,该如何处理呢?
jquery stop(): 如:$(“#div”).stop().animate({width:”100px”},100);
把 Script 标签 放在页面的最底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?
移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?(click 有 300ms 延迟,为了实现safari的双击事件的设计,浏览器要知道你是不是要双击操作。)
知道各种JS框架(Angular, Backbone, Ember, React, Meteor, Knockout…)么? 能讲出他们各自的优点和缺点么?
Underscore 对哪些 JS 原生对象进行了扩展以及提供了哪些好用的函数方法?
解释JavaScript中的作用域与变量声明提升?
那些操作会造成内存泄漏?
内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。

setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
JQuery一个对象可以同时绑定多个事件,这是如何实现的?
多个事件同一个函数:
$(“div”).on(“click mouseover”, function(){});
多个事件不同函数
$(“div”).on({
click: function(){},
mouseover: function(){}
});
Node.js的适用场景?
(如果会用node)知道route, middleware, cluster, nodemon, pm2, server-side rendering么?
解释一下 Backbone 的 MVC 实现方式?
什么是“前端路由”?什么时候适合使用“前端路由”? “前端路由”有哪些优点和缺点?
知道什么是webkit么? 知道怎么用浏览器的各种工具来调试和debug代码么?
Chrome,Safari浏览器内核。
如何测试前端代码么? 知道BDD, TDD, Unit Test么? 知道怎么测试你的前端工程么(mocha, sinon, jasmin, qUnit..)?
前端templating(Mustache, underscore, handlebars)是干嘛的, 怎么用?
简述一下 Handlebars 的基本用法?
简述一下 Handlerbars 的对模板的基本处理流程, 如何编译的?如何缓存的?
用js实现千位分隔符?(来源:前端农民工,提示:正则+replace)
参考:http://www.tuicool.com/articles/ArQZfui
function commafy(num) {
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+.)/g, function($0, $1) {
return $1 + “,”;
});
}
console.log(commafy(1234567.90)); //1,234,567.90
检测浏览器版本版本有哪些方式?
功能检测、userAgent特征检测

比如:navigator.userAgent
//“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36”
What is a Polyfill?
polyfill 是“在旧版浏览器上复制标准 API 的 JavaScript 补充”,可以动态地加载 JavaScript 代码或库,在不支持这些标准 API 的浏览器中模拟它们。
例如,geolocation(地理位置)polyfill 可以在 navigator 对象上添加全局的 geolocation 对象,还能添加 getCurrentPosition 函数以及“坐标”回调对象,
所有这些都是 W3C 地理位置 API 定义的对象和函数。因为 polyfill 模拟标准 API,所以能够以一种面向所有浏览器未来的方式针对这些 API 进行开发,
一旦对这些 API 的支持变成绝对大多数,则可以方便地去掉 polyfill,无需做任何额外工作。
做的项目中,有没有用过或自己实现一些 polyfill 方案(兼容性处理方案)?
比如: html5shiv、Geolocation、Placeholder
我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡。会执行几次事件,会先执行冒泡还是捕获?
使用JS实现获取文件扩展名?
function getFileExtension(filename) {
return filename.slice((filename.lastIndexOf(“.”) - 1 >>> 0) + 2);
}

String.lastIndexOf() 方法返回指定值(本例中的’.’)在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。
对于’filename’和’.hiddenfile’,lastIndexOf的返回值分别为0和-1无符号右移操作符(»>) 将-1转换为4294967295,将-2转换为4294967294,这个方法可以保证边缘情况时文件名不变。
String.prototype.slice() 从上面计算的索引处提取文件的扩展名。如果索引比文件名的长度大,结果为””。
Webpack热更新实现原理?
1. Webpack编译期,为需要热更新的 entry 注入热更新代码(EventSource通信)
2. 页面首次打开后,服务端与客户端通过 EventSource 建立通信渠道,把下一次的 hash 返回前端
3. 客户端获取到hash,这个hash将作为下一次请求服务端 hot-update.js 和 hot-update.json的hash
4. 修改页面代码后,Webpack 监听到文件修改后,开始编译,编译完成后,发送 build 消息给客户端
5. 客户端获取到hash,成功后客户端构造hot-update.js script链接,然后插入主文档
6. hot-update.js 插入成功后,执行hotAPI 的 createRecord 和 reload方法,获取到 Vue 组件的 render方法,重新 render 组件, 继而实现 UI 无刷新更新。
请介绍一下JS之事件节流?
什么是JS的函数防抖?
ECMAScript6 相关
Object.is() 与原来的比较操作符“ ===”、“ ==”的区别?
两等号判等,会在比较时进行类型转换;
三等号判等(判断严格),比较时不进行隐式类型转换,(类型不同则会返回false);

Object.is 在三等号判等的基础上特别处理了 NaN 、-0 和 +0 ,保证 -0 和 +0 不再相同,
但 Object.is(NaN, NaN) 会返回 true.

Object.is 应被认为有其特殊的用途,而不能用它认为它比其它的相等对比更宽松或严格。
ES6是如何实现编译成ES5的?
css-loader的原理?
前端框架
React 使用场景?
逻辑复杂单页应用,偏中后台管理系统,纯展示性的UI页面不合适、
描述一下React 生命周期
渲染过程调用到的生命周期函数,主要几个要知道;
constructor

getInitialState

getDefaultProps

componentWillMount

render

componentDidMount


  更新过程

  * componentWillReceiveProps
<br />      * shouldComponentUpdate
<br />      * componentWillUpdate
<br />      * render
<br />      * componentDidUpdate


  卸载过程

  componentWillUnmount<br />实现组件有哪些方式?<br />  React.createClass 使用API来定义组件<br />  React ES6 class component 用 ES6 的class 来定义组件<br />  Functional stateless component 通过函数定义无状态组件<br />应该在React生命周期的什么阶段发出ajax请求,为什么?<br />          AJAX请求应在 componentDidMount函数 进行请求。<br />shouldComponentUpdate函数有什么作用?<br />          shouldComponentUpdate是一个允许我们自行决定某些组件(以及他们的子组件)是否进行更新的生命周期函数,reconciliation的最终目的是尽可能以最有效的方式去根据新的state更新UI,<br />          如果你已经知道UI的哪些状态无需进行改变,就没必要去让React去判断它是否该改变。 让shouldComponentUpdate返回falss, React就会让当前的组件和其子组件保持不变。<br />当组件的setState函数被调用之后,发生了什么?<br />          React会做的第一件事就是把你传递给setState的参数对象合并到组件原先的state。这个事件会导致一个“reconciliation”(调和)的过程。reconciliation的最终目标就是,<br />          尽可能以最高效的方法,去基于新的state来更新UI。为了达到这个目的,React会构建一个React元素树(你可以把这个想象成一个表示UI的一个对象)。一旦这个树构建完毕,<br />          React为了根据新的state去决定UI要怎么进行改变,它会找出这棵新树和旧树的不同之处。React能够相对精确地找出哪些位置发生了改变以及如何发生了什么变化,<br />          并且知道如何只通过必要的更新来最小化重渲染。<br />为什么循环产生的组件中要利用上key这个特殊的prop?<br />          Keys负责帮助React跟踪列表中哪些元素被改变/添加/移除。React利用子元素的key在比较两棵树的时候,快速得知一个元素是新的还是刚刚被移除。没有keys,React也就不知道当前哪一个的item被移除了。<br />React-router 路由的实现原理?<br />说说React Native,Weex框架的实现原理?<br />受控组件(Controlled Component)与非受控组件(Uncontrolled Component)的区别<br />refs 是什么?<br />      Refs是能访问DOM元素或组件实例的一个函数;<br />React为什么自己定义一套事件体系呢,与浏览器原生事件体系有什么关系?<br />什么时候应该选择用class实现一个组件,什么时候用一个函数实现一个组件?<br />      组件用到了state或者用了生命周期函数,那么就该使用Class component。其他情况下,应使用Functional component。<br />什么是HoC(Higher-Order Component)?适用于什么场景?<br />      高阶组件就是一个 React 组件包裹着另外一个 React 组件<br />并不是父子关系的组件,如何实现相互的数据通信?<br />      使用父组件,通过props将变量传入子组件
(如通过refs,父组件获取一个子组件的方法,简单包装后,将包装后的方法通过props传入另一个子组件
)<br />用过 React 技术栈中哪些数据流管理库?<br />      Redux\Dva<br />Redux是如何做到可预测呢?<br />Redux将React组件划分为哪两种?<br />Redux是如何将state注入到React组件上的?<br />请描述一次完整的 Redux 数据流<br />React的批量更新机制 BatchUpdates?<br />React与Vue,各自的组件更新进行对比,它们有哪些区别?<br />其他问题<br />原来公司工作流程是怎么样的,如何与其他人协作的?如何跨部门合作的?<br />你遇到过比较难的技术问题是?你是如何解决的?<br />设计模式 知道什么是singleton, factory, strategy, decrator么?<br />常使用的库有哪些?常用的前端开发工具?开发过什么应用或组件?<br />页面重构怎么操作?<br />  网站重构:在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为。<br />  也就是说是在不改变UI的情况下,对网站进行优化,在扩展的同时保持一致的UI。

对于传统的网站来说重构通常是:

表格(table)布局改为DIV+CSS
使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)
对于移动平台的优化
针对于SEO进行优化
深层次的网站重构应该考虑的方面

减少代码间的耦合
让代码保持弹性
严格按规范编写代码
设计可扩展的API
代替旧有的框架、语言(如VB)
增强用户体验
通常来说对于速度的优化也包含在重构中

压缩JS、CSS、image等前端资源(通常是由服务器来解决)
程序的性能优化(如数据读写)
采用CDN来加速资源加载
对于JS DOM的优化
HTTP服务器的文件缓存
列举IE与其他浏览器不一样的特性?
1、事件不同之处:

     触发事件的元素被认为是目标(target)。而在 IE 中,目标包含在 event 对象的 srcElement 属性;

  获取字符代码、如果按键代表一个字符(shift、ctrl、alt除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是分离的,要获取字符代码,需要使用 charCode 属性;

  阻止某个事件的默认行为,IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,需要调用 preventDefault() 方法;

  停止事件冒泡,IE 中阻止事件进一步冒泡,需要设置 cancelBubble 为 true,Mozzilla 中,需要调用 stopPropagation();<br />99%的网站都需要被重构是那本书上写的?<br />  网站重构:应用web标准进行设计(第2版)<br />什么叫优雅降级和渐进增强?<br />  优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会针对旧版本的IE进行降级处理了,使之在旧式浏览器上以某种形式降级体验却不至于完全不能用。<br />  如:border-shadow

渐进增强:从被所有浏览器支持的基本功能开始,逐步地添加那些只有新版本浏览器才支持的功能,向页面增加不影响基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。
如:默认使用flash上传,但如果浏览器支持 HTML5 的文件上传功能,则使用HTML5实现更好的体验;
是否了解公钥加密和私钥加密。
一般情况下是指私钥用于对数据进行签名,公钥用于对签名进行验证;
HTTP网站在浏览器端用公钥加密敏感数据,然后在服务器端再用私钥解密。
WEB应用从服务器主动推送Data到客户端有那些方式?
html5提供的Websocket
不可见的iframe
WebSocket通过Flash
XHR长时间连接
XHR Multipart Streaming

CORS:
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
通过修改document.domain来跨子域
将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域
主域相同的使用document.domain
使用window.name来进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的
使用HTML5中新引进的window.postMessage方法来跨域传送数据
还有flash、在服务器上设置代理页面等跨域方式。个人认为window.name的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。
XML和JSON的区别?
(1).数据体积方面。
JSON相对于XML来讲,数据的体积小,传递的速度更快些。
(2).数据交互方面。
JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。
(3).数据描述方面。
JSON对数据的描述性比XML较差。
(4).传输速度方面。
JSON的速度要远远快于XML。
谈谈你对webpack的看法
WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。
webpack的两大特色:
1.code splitting(可以自动完成)
2.loader 可以处理各种类型的静态文件,并且支持串联操作
webpack 是以commonJS的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
webpack具有requireJs和browserify的功能,但仍有很多自己的新特性:
1. 对 CommonJS 、 AMD、ES6的语法做了兼容
2. 对js、css、图片等资源文件都支持打包
3. 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持
4. 有独立的配置文件webpack.config.js
5. 可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间
6. 支持 SourceUrls 和SourceMaps,易于调试
7. 具有强大的Plugin接口,大多是内部插件,使用起来比较灵活
8.webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快
说说TCP传输的三次握手四次挥手策略
为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。用TCP协议把数据包送出去后,TCP不会对传送 后的情况置之不理,它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志:SYN和ACK。
发送端首先发送一个带SYN标志的数据包给对方。接收端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息。
最后,发送端再回传一个带ACK标志的数据包,代表“握手”结束。
若在握手过程中某个阶段莫名中断,TCP协议会再次以相同的顺序发送相同的数据包。

断开一个TCP连接则需要“四次握手”:
§ 第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
§ 第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
§ 第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
§ 第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
TCP和UDP的区别
TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!
UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。
说说你对作用域链的理解
作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。
创建ajax过程
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
渐进增强和优雅降级
渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
常见web安全及防护原理
sql注入原理
就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
总的来说有以下几点:
1.永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双”-“进行转换等。
2.永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
XSS原理及防范
Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意 html标签或者javascript代码。比如:攻击者在论坛中放一个
看似安全的链接,骗取用户点击后,窃取cookie中的用户私密信息;或者攻击者在论坛中加一个恶意表单,
当用户提交表单的时候,却把信息传送到攻击者的服务器中,而不是用户原本以为的信任站点。
XSS防范方法
首先代码里对用户输入的地方和变量都需要仔细检查长度和对”<”,”>”,”;”,”’”等字符做过滤;其次任何内容写到页面之前都必须加以encode,避免不小心把html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS 攻击。
首先,避免直接在cookie 中泄露用户隐私,例如email、密码等等。
其次,通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。
如果网站不需要再浏览器端对cookie 进行操作,可以在Set-Cookie 末尾加上HttpOnly 来防止javascript 代码直接获取cookie 。
尽量采用POST 而非GET 提交表单
XSS与CSRF有什么区别吗?
XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。
要完成一次CSRF攻击,受害者必须依次完成两个步骤:
登录受信任网站A,并在本地生成Cookie。

在不登出A的情况下,访问危险网站B。
CSRF的防御
§ 服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
§ 通过验证码的方法
Web Worker 和webSocket
worker主线程:
1.通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。
2.通过worker.postMessage( data) 方法来向worker发送数据。
3.绑定worker.onmessage方法来接收worker发送过来的数据。
4.可以使用 worker.terminate() 来终止一个worker的执行。
WebSocket是Web应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个Html5协议,WebSocket的连接是持久的,他通过在客户端和服务器之间保持双工连接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定时间间隔去轮询。
HTTP和HTTPS
HTTP协议通常承载于TCP协议之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS。
默认HTTP的端口号为80,HTTPS的端口号为443。
为什么HTTPS安全
因为网络请求需要中间有很多的服务器路由器的转发。中间的节点都可能篡改信息,而如果使用HTTPS,密钥在你和终点站才有。https之所以比http安全,是因为他利用ssl/tls协议传输。它包含证书,卸载,流量转发,负载均衡,页面适配,浏览器适配,refer传递等。保障了传输过程的安全性
对前端模块化的认识
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
AMD 是提前执行,CMD 是延迟执行。
AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。
CMD模块方式
define(function(require, exports,module) {
// 模块代码
});
Javascript垃圾回收方法
标记清除(mark and sweep)
这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
引用计数(reference counting)
在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的,
也就是说只要涉及BOM及DOM就会出现循环引用问题。
你觉得前端工程的价值体现在哪
为简化用户使用提供技术支持(交互部分)
为多个浏览器兼容性提供支持
为提高用户浏览速度(浏览器性能)提供支持
为跨平台或者其他基于webkit或其他渲染引擎的应用提供支持
为展示数据提供支持(数据接口)
谈谈性能优化问题
代码层面:避免使用css表达式,避免使用高级选择器,通配选择器。
缓存利用:缓存Ajax,使用CDN,使用外部js和css文件以便缓存,添加Expires头,服务端配置Etag,减少DNS查找等
请求数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载。
请求带宽:压缩文件,开启GZIP,
代码层面的优化
用hash-table来优化查找
少用全局变量
用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
用setTimeout来避免页面失去响应
缓存DOM节点查找的结果
避免使用CSS Expression
避免全局查询
避免使用with(with会创建自己的作用域,会增加作用域链长度)
多个变量声明合并
避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率
尽量避免写在HTML标签中写Style属性
移动端性能优化
尽量使用css3动画,开启硬件加速。
适当使用touch事件代替click事件。
避免使用css3渐变阴影效果。
可以用transform: translateZ(0)来开启硬件加速。
不滥用Float。Float在渲染时计算量比较大,尽量减少使用
不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。
合理使用requestAnimationFrame动画代替setTimeout
CSS中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发GPU渲染,请合理使用。过渡使用会引发手机过耗电增加
PC端的在移动端同样适用
相关阅读:如何做到一秒渲染一个移动页面
什么是Etag?
当发送一个服务器请求时,浏览器首先会进行缓存过期判断。浏览器根据缓存过期时间判断缓存文件是否过期。
情景一:若没有过期,则不向服务器发送请求,直接使用缓存中的结果,此时我们在浏览器控制台中可以看到 200 OK(from cache) ,此时的情况就是完全使用缓存,浏览器和服务器没有任何交互的。
情景二:若已过期,则向服务器发送请求,此时请求中会带上①中设置的文件修改时间,和Etag
然后,进行资源更新判断。服务器根据浏览器传过来的文件修改时间,判断自浏览器上一次请求之后,文件是不是没有被修改过;根据Etag,判断文件内容自上一次请求之后,有没有发生变化
情形一:若两种判断的结论都是文件没有被修改过,则服务器就不给浏览器发index.html的内容了,直接告诉它,文件没有被修改过,你用你那边的缓存吧—— 304 Not Modified,此时浏览器就会从本地缓存中获取index.html的内容。此时的情况叫协议缓存,浏览器和服务器之间有一次请求交互。
情形二:若修改时间和文件内容判断有任意一个没有通过,则服务器会受理此次请求,之后的操作同①
① 只有get请求会被缓存,post请求不会
Expires和Cache-Control
Expires要求客户端和服务端的时钟严格同步。HTTP1.1引入Cache-Control来克服Expires头的限制。如果max-age和Expires同时出现,则max-age有更高的优先级。
Cache-Control:no-cache, private, max-age=0
ETag: abcde
Expires: Thu, 15 Apr 201420:00:00 GMT
Pragma: private
Last-Modified:$now //RFC1123 format
ETag应用:
Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match。请求一个文件的流程可能如下:
====第一次请求===
1.客户端发起 HTTP GET 请求一个文件;
2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如”2e681a-6-5d044840”)(假设服务器支持Etag生成和已经开启了Etag).状态码200
====第二次请求===
客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag:2e681a-6-5d0448402.服务器判断发送过来的Etag和计算出来的Etag匹配,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;流程很简单,问题是,如果服务器又设置了Cache-Control:max-age和Expires呢,怎么办
答案是同时使用,也就是说在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,
服务器才能返回304.(不要陷入到底使用谁的问题怪圈)
为什么使用Etag请求头?
Etag 主要为了解决 Last-Modified 无法解决的一些问题。
栈和队列的区别?
栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
队列先进先出,栈先进后出。
栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除
栈和堆的区别?
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。

堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。
堆(数据结构):堆可以被看成是一棵树,如:堆排序;
栈(数据结构):一种先进后出的数据结构。
快速 排序的思想并实现一个快排?
“快速排序”的思想很简单,整个排序过程只需要三步:
  (1)在数据集之中,找一个基准点
  (2)建立两个数组,分别存储左边和右边的数组
  (3)利用递归进行下次比较

functionquickSort(arr){
if(arr.length<=1){
return arr;//如果数组只有一个数,就直接返回;
}

var num = Math.floor(arr.length/2);//找到中间数的索引值,如果是浮点数,则向下取整
var numValue =arr.splice(num,1);//找到中间数的值
var left = [];
var right = [];
for(var i=0;i if(arr[i] left.push(arr[i]);//基准点的左边的数传到左边数组
}
else{
right.push(arr[i]);//基准点的右边的数传到右边数组
}
}
returnquickSort(left).concat([numValue],quickSort(right));//递归不断重复比较
}

alert(quickSort([32,45,37,16,2,87]));//弹出“2,16,32,37,45,87”

你觉得jQuery或zepto源码有哪些写的好的地方
(答案仅供参考)
jQuery源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染,然后通过传入window对象参数,可以使window对象作为局部变量使用,好处是当jquery中访问window对象的时候,就不用将作用域链退回到顶层作用域了,从而可以更快的访问window对象。同样,传入undefined参数,可以缩短查找undefined时的作用域链。
(function( window, undefined ) {

//用一个函数域包起来,就是所谓的沙箱

//在这里边var定义的变量,属于这个函数域内的局部变量,避免污染全局

//把当前沙箱需要的外部变量通过函数参数引入进来

//只要保证参数对内提供的接口的一致性,你还可以随意替换传进来的这个参数

window.jQuery = window.$ = jQuery;

})( window );

jquery将一些原型属性和方法封装在了jquery.prototype中,为了缩短名称,又赋值给了jquery.fn,这是很形象的写法。
有一些数组或对象的方法经常能使用到,jQuery将其保存为局部变量以提高访问速度。
jquery实现的链式调用可以节约代码,所返回的都是同一个对象,可以提高代码效率。
ES6的了解
新增模板字符串(为JavaScript提供了简单的字符串插值功能)、箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。)、for-of(用来遍历数据—例如数组中的值。)arguments对象可被不定参数和默认参数完美代替。ES6将promise对象纳入规范,提供了原生的Promise对象。增加了let和const命令,用来声明变量。增加了块级作用域。let命令实际上就增加了块级作用域。ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。。还有就是引入module模块的概念
js继承方式及其优缺点
原型链继承的缺点
一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。
借用构造函数(类式继承)
借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承
组合式继承
组合式继承是比较常用的一种继承方法,其背后的思路是 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。
关于Http 2.0 你知道多少?
HTTP/2引入了“服务端推(server push)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能。
HTTP/2提供更多的加密支持
HTTP/2使用多路技术,允许多个消息在一个连接上同时交差。
它增加了头压缩(header compression),因此即使非常小的请求,其请求和响应的header都只会占用很小比例的带宽。

defer和async
defer并行加载js文件,会按照页面上script标签的顺序执行
async并行加载js文件,下载完成立即执行,不会按照页面上script标签的顺序执行
谈谈浮动和清除浮动
浮动的框可以向左或向右移动,直到他的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流的块框表现得就像浮动框不存在一样。浮动的块框会漂浮在文档普通流的块框上。
如何评价AngularJS和BackboneJS
backbone具有依赖性,依赖underscore.js。Backbone + Underscore + jQuery(or Zepto) 就比一个AngularJS 多出了2 次HTTP请求.

Backbone的Model没有与UI视图数据绑定,而是需要在View中自行操作DOM来更新或读取UI数据。AngularJS与此相反,Model直接与UI视图绑定,Model与UI视图的关系,通过directive封装,AngularJS内置的通用directive,就能实现大部分操作了,也就是说,基本不必关心Model与UI视图的关系,直接操作Model就行了,UI视图自动更新。

AngularJS的directive,你输入特定数据,他就能输出相应UI视图。是一个比较完善的前端MVW框架,包含模板,数据双向绑定,路由,模块化,服务,依赖注入等所有功能,模板功能强大丰富,并且是声明式的,自带了丰富的 Angular 指令。
用过哪些设计模式?
工厂模式:
主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。

工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。


function createObject(name,age,profession){//集中实例化的函数var obj = newObject();
obj.name =name;
obj.age = age;
obj.profession= profession;
obj.move =function () {
returnthis.name + ‘ at ‘ + this.age + ‘ engaged in ‘ + this.profession;
};
return obj;
}
var test1 = createObject(‘trigkit4’,22,’programmer’);//第一个实例var test2 =createObject(‘mike’,25,’engineer’);//第二个实例

构造函数模式
使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于:
1.构造函数方法没有显示的创建对象 (new Object());
2.直接将属性和方法赋值给 this 对象;
3.没有 renturn 语句。
说说你对闭包的理解
使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念
闭包有三个特性:
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
请你谈谈Cookie的弊端
cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的。
第一:每个特定的域名下最多生成20个cookie
1.IE6或更低版本最多20个cookie
2.IE7和之后的版本最后可以有50个cookie。
3.Firefox最多50个cookie
4.chrome和Safari没有做硬性限制
IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie。
cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节。
IE 提供了一种存储可以持久化用户数据,叫做userdata,从IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。
优点:极高的扩展性和可用性
1.通过良好的编程,控制保存在cookie中的session对象的大小。
2.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
3.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
4.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。
缺点:
1.Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉.
2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。
浏览器本地存储
在较高版本的浏览器中,js提供了sessionStorage和globalStorage。在HTML5中提供了localStorage来取代globalStorage。
html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage。
sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。
而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
web storage和cookie的区别
Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。
除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。
但是cookie也是不可以或缺的:cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生
浏览器的支持除了IE7及以下不支持外,其他标准浏览器都完全支持(ie及FF需在web服务器里运行),值得一提的是IE总是办好事,例如IE7、IE6中的userData其实就是javascript本地存储的解决方案。通过简单的代码封装可以统一到所有的浏览器都支持web storage。
localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
display:none和visibility:hidden的区别?
display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。
CSS中link 和@import的区别是?
(1) link属于HTML标签,而@import是CSS提供的;
(2) 页面被加载的时,link会同时被加载,而@import被引用的CSS会等到引用它的CSS文件被加载完再加载;
(3) import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
(4) link方式的样式的权重 高于@import的权重.
position:absolute和float属性的异同
§ 共同点:对内联元素设置float和absolute属性,可以让元素脱离文档流,并且可以设置其宽高。
§ 不同点:float仍会占据位置,absolute会覆盖文档流中的其他元素。
介绍一下box-sizing属性?
box-sizing属性主要用来控制元素的盒模型的解析模式。默认值是content-box。
§ content-box:让元素维持W3C的标准盒模型。元素的宽度/高度由border + padding + content的宽度/高度决定,设置width/height属性指的是content部分的宽/高
§ border-box:让元素维持IE传统盒模型(IE6以下版本和IE6~7的怪异模式)。设置width/height属性指的是border + padding + content
标准浏览器下,按照W3C规范对盒模型解析,一旦修改了元素的边框或内距,就会影响元素的盒子尺寸,就不得不重新计算元素的盒子尺寸,从而影响整个页面的布局。
CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(lia)
7.通配符选择器(
8.属性选择器(a[rel = “external”])
9.伪类选择器(a: hover, li:nth-child)
优先级为:
!important > id > class > tag
important 比 内联优先级高,但内联比 id 要高
CSS3新增伪类举例:
p:first-of-type选择属于其父元素的首个

元素的每个

元素。
p:last-of-type 选择属于其父元素的最后

元素的每个

元素。

p:only-of-type 选择属于其父元素唯一的

元素的每个

元素。
p:only-child 选择属于其父元素的唯一子元素的每个

元素。
p:nth-child(2) 选择属于其父元素的第二个子元素的每个

元素。
:enabled :disabled控制表单控件的禁用状态。
:checked 单选框或复选框被选中。
CSS3有哪些新特性?
CSS3实现圆角(border-radius),阴影(box-shadow),
对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)
transform:rotate(9deg) scale(0.85,0.90)translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜
增加了更多的CSS选择器 多背景 rgba
在CSS3中唯一引入的伪元素是::selection.
媒体查询,多栏布局
border-image
CSS3中新增了一种盒模型计算方式:box-sizing。盒模型默认的值是content-box, 新增的值是padding-box和border-box,几种盒模型计算元素宽高的区别如下:
content-box(默认)
布局所占宽度Width:
Width = width + padding-left + padding-right + border-left + border-right
布局所占高度Height:
Height = height + padding-top + padding-bottom + border-top + border-bottom
padding-box
布局所占宽度Width:
Width = width(包含padding-left + padding-right) + border-top + border-bottom
布局所占高度Height:
Height = height(包含padding-top + padding-bottom) + border-top + border-bottom
border-box
布局所占宽度Width:
Width = width(包含padding-left + padding-right + border-left + border-right)
布局所占高度Height:
Height = height(包含padding-top + padding-bottom + border-top + border-bottom)
对BFC规范的理解?
BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的margin会发生折叠。
(W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行布局,以及与其他元素的关系和相互作用。
说说你对语义化的理解?
1,去掉或者丢失样式的时候能够让页面呈现出清晰的结构
2,有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
3,方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
4,便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?
1)、<!DOCTYPE> 声明位于文档中的最前面,处于 标签之前。告知浏览器以何种模式来渲染文档。
2)、严格模式的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。
3)、在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。
4)、DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。
你知道多少种Doctype文档类型?
该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。
HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。
XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。
Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks
(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。
HTML与XHTML——二者有什么区别
区别:

1.所有的标记都必须要有一个相应的结束标记
2.所有标签的元素和属性的名字都必须使用小写
3.所有的XML标记都必须合理嵌套
4.所有的属性必须用引号””括起来
5.把所有<和&特殊符号用编码表示
6.给所有属性赋一个值
7.不要在注释内容中使“—”
8.图片必须有说明文字
常见兼容性问题?
png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.也可以引用一段脚本处理.
浏览器默认的margin和padding不同。解决方案是加一个全局的
{margin:0;padding:0;}来统一。
IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。)
#box{ float:left; width:10px; margin:0 0 0 100px;}
这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入
display:inline;将其转化为行内属性。(这个符号只有ie6会识别)
渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。
接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css
.bb{
background-color:#f1ee18;/所有识别/
.background-color:#00deff\9; /IE6、7、8识别/
+background-color:#a200ff;/IE6、7识别/
background-color:#1e0bd1;/IE6识别/

}
怪异模式问题:漏写DTD声明,Firefox仍然会按照标准模式来解析网页,但在IE中会触发
怪异模式。为避免怪异模式给我们带来不必要的麻烦,最好养成书写DTD声明的好习惯。现在
可以使用html5推荐的写法:<doctype html>
上下margin重合问题
ie和ff都存在,相邻的两个div的margin-left和margin-right不会重合,但是margin-top和margin-bottom却会发生重合。
解决方法,养成良好的代码编写习惯,同时采用margin-top或者同时采用margin-bottom。
解释下浮动和它的工作原理?清除浮动的技巧
浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。
1.使用空标签清除浮动。
这种方法是在所有浮动标签后面添加一个空标签 定义cssclear:both. 弊端就是增加了无意义标签。
2.使用overflow。
给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。
3.使用after伪对象清除浮动。
该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;
浮动元素引起的问题和解决办法?
浮动元素引起的问题:
(1)父元素的高度无法被撑开,影响与父元素同级的元素
(2)与浮动元素同级的非浮动元素(内联元素)会跟随其后
(3)若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构
解决方法:
使用CSS中的clear:both;属性来清除元素的浮动可解决2、3问题,对于问题1,添加如下样式,给父元素添加clearfix样式:
.clearfix:after{content:”.”;display: block;height:0;clear: both;visibility: hidden;}
.clearfix{display: inline-block;} / for IE/Mac /
清除浮动的几种方法:
1,额外标签法,(缺点:不过这个办法会增加额外的标签使HTML结构看起来不够简洁。)
2,使用after伪类
#parent:after{
content:”.”;
height:0;
visibility:hidden;
display:block;
clear:both;
}
3,浮动外部元素
4,设置overflow为hidden或者auto
DOM操作——怎样添加、移除、移动、复制、创建和查找节点。
1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //并没有insertAfter()
3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,
会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
拖拽释放(Drag and drop) API
语义化更好的内容标签(header,nav,footer,aside,article,section)
音频、视频API(audio,video)
画布(Canvas) API
地理(Geolocation) API
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
sessionStorage 的数据在浏览器关闭后自动删除
表单控件,calendar、date、time、email、url、search
新的技术webworker, websocket,Geolocation
移除的元素
纯表现的元素:basefont,big,center,font, s,strike,tt,u;

对可用性产生负面影响的元素:frame,frameset,noframes;
支持HTML5新标签:
IE8/IE7/IE6支持通过document.createElement方法产生的标签,
可以利用这一特性让这些浏览器支持HTML5新标签,
当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架

如何区分: DOCTYPE声明\新增的结构元素\功能元素
如何实现浏览器内多个标签页之间的通信?
调用localstorge、cookies等本地存储方式
什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?
FOUC - FlashOf Unstyled Content 文档样式闪烁


而引用CSS文件的@import就是造成这个问题的罪魁祸首。IE会先加载整个HTML文档的DOM,然后再去导入外部的CSS文件,因此,在页面DOM加载完成到CSS导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。
解决方法简单的出奇,只要在之间加入一个或者




remote.js文件代码如下:
localHandler({“result”:”我是远程js带来的数据”});
1
运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。
很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。
3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端 “我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
看jsonp.html页面的代码:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">








这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。
我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html
(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):
HTML 代码
flightHandler({
“code”: “CA1998”,
“price”: 1780,
“tickets”: 5
});
我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!
4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。
jQuery如何实现jsonp调用?
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<script type=”text/javascript” src=jquery.min.js”>





这里针对ajax与jsonp的异同再做一些补充说明:
1、ajax和jsonp这两种技术在调用方式上”看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加script标签来调用服务器提供的js脚本。
3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。
总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!
2、手写单链表查找倒数第k个节点
1、为了找出倒数第k个元素,最容易想到的办法是首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第k个,转换为正数第n-k个,接下来遍历一次就可以得到结果。但是该方法存在一个问题,即需要对链表进行两次遍历,第一次遍历用于求解单链表的长度,第二次遍历用于查找正数第n-k个元素。
这种思路的时间复杂度是O(n),但需要遍历链表两次。
2、如果我们在遍历时维持两个指针,第一个指针从链表的头指针开始遍历,在第k-1步之前,第二个指针保持不动;在第k-1步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第k个结点。这种思路只需要遍历链表一次。对于很长的链表,只需要把每个结点从硬盘导入到内存一次。因此这一方法的时间效率前面的方法要高。
class Node{
Node next=null;
int data;
public Node(int data){
this.data=data;
}
}
public class MyLinkedList {

Node head=null;//链表头的引用<br />    public Node findElem(Node head,int k){<br />        if(k<1||k>this.length()){<br />            return null;<br />        }<br />        Node p1=head;<br />        Node p2=head;<br />        for(int i=0;i<k;i++)<br />            p1=p1.next;<br />        while(p1!=null){<br />            p1=p1.next;<br />            p2=p2.next;<br />        }<br />        return p2;<br />    }<br />    public static void main(String[] args) {

    MyLinkedList list=new MyLinkedList();<br />        list.addNode(1);<br />        list.addNode(2);<br />        list.addNode(3);<br />        list.addNode(4);<br />        list.addNode(5);<br />        MyLinkedList p=new MyLinkedList();<br />        p.head=list.findElem(list.head, 3);<br />        p.printList();

}

}
3、http请求头,请求体,cookie在哪个里面?url在哪里面?
参考菜鸟教程HTTP专栏:http://www.runoob.com/http/http-tutorial.html
人人三面的时候问我http请求头都有哪些值,答不上来。。GG
客户端请求消息
WEB   试题 - 图12
服务器响应消息
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
WEB   试题 - 图13
实例
下面实例是一点典型的使用GET来传递数据的实例:
客户端请求:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
服务端响应:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: “34aa387-d-1568eb00”
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
输出结果:
Hello World! My payload includes a trailing CRLF.1
4、原型链的解释
饿了么面试的时候问到了,用友也问到了。没答好,GG.
WEB   试题 - 图14
5、对闭包的理解,实现一个暴露内部变量,而且外部可以访问修改的函数
闭包的作用:
匿名自执行函数、缓存、实现封装(主要作用)、实现面向对象中的对象
var person = function(){
//变量作用域为函数内部,外部无法访问
var name = “default”;
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();
print(person.name);//直接访问,结果为undefined
print(person.getName());
person.setName(“a”);
print(person.getName());
//得到结果如下:
undefined
default
6、基本的数据类型
5个简单数据类型(基本数据类型)+ 1个复杂数据类型
undefiend, number string null boolean + object
ES6 新增Symbol
7、基本的两列自适应布局
左定右适应:
#div1{
width: 100px;
display: inline-block;
background-color: black;
}
#div2{
display: inline-block;
position: absolute;
left: 100px;
right: 0px;
background-color: red;
}
8、unix中常用的命令行
虽然上过linux课,但是命令忘得差不多了 尴尬。。。
9、OSI模型,HTTP,TCP,UDP分别在哪些层
这个可以参考我另一个博客:
http://blog.csdn.net/qq_22944825/article/details/78160659
OSI:物理层-数据链路层-网络层-传输层-会话层-表现层-应用层
WEB   试题 - 图15
10、解释平衡二叉树,以及在数据结构中的应用(红黑树)
11、快排的时间复杂度和空间复杂度
一个特别好的总结的博客:
http://web.jobbole.com/87968/
12、手写一个jQuery插件
1、$.extend(src)
  该方法就是将src合并到jquery的全局对象中去,如:
$.extend({
hello:function(){alert(‘hello’);}
});
2、$.fn.extend(src)
  该方法将src合并到jquery的实例对象中去,如:
$.fn.extend({
hello:function(){alert(‘hello’);}
});
13、在jquery方法和原型上面添加方法的区别和实现,以及jquery对象的实现
参考上一个问题答案~
使用jquery的第一件事就是要使用jquery对象,jquery对象和javascript中的DOM对象是不同的。
什么是jquery对象?jquery将一个DOM对象转化为jquery对象后就可以使用jquery类库提供的各种函数。可以将jquery对象理解为一个类,并且封装了很多的方法,而且可以动态的通过加载插件扩展这个类,类似于C#中的分布类partial class。
除了jQuery工具函数,jQuery的操作都是从jQuery对象开始。比如:
attr(key,value)

my photo

$(“#myphoto”).attr(“src”,”/pic/1.jpg”);
jQuery对象是一个特殊的集合对象。即使只有一个元素,jQuery对象仍然是一个集合。说其特殊是因为实际上jQuery对象是包含一个集合对象和各种函数的类。
14、手写一个递归函数
function fact(num) {
if (num <= 1) {
return 1;
} else {
return num fact(num - 1);
}
}
以下代码可导致出错:
var anotherFact = fact;
fact = null;
alert(antherFact(4)); //出错
由于fact已经不是函数了,所以出错。
用arguments.callee可解决问题,这是一个指向正在执行的函数的指针,arguments.callee返回正在被执行的对现象。
新的函数为:
function fact(num) {
if (num <= 1) {
return 1;
} else {
return num
arguments.callee(num - 1); //此处更改了。
}
}
var anotherFact = fact;
fact = null;
alert(antherFact(4)); //结果为24.
15、对前端路由的理解?前后端路由的区别?
前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的。在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。
http://10.0.0.1/
http://10.0.0.1/#/about
http://10.0.0.1/#/concat
服务端路由:每跳转到不同的URL,都是重新访问服务端,然后服务端返回页面,页面也可以是服务端获取数据,然后和模板组合,返回HTML,也可以是直接返回模板HTML,然后由前端JS再去请求数据,使用前端模板和数据进行组合,生成想要的HTML。
前端路由:每跳转到不同的URL都是使用前端的锚点路由,实际上只是JS根据URL来操作DOM元素,根据每个页面需要的去服务端请求数据,返回数据后和模板进行组合,当然模板有可能是请求服务端返回的,这就是 SPA 单页程序。
在js可以通过window.location.hash读取到路径加以解析之后就可以响应不同路径的逻辑处理。
history 是 HTML5 才有的新 API,可以用来操作浏览器的 session history (会话历史)。基于 history 来实现的路由可以和最初的例子中提到的路径规则一样。
H5还新增了一个hashchange事件,也是很有用途的一个新事件:
当页面hash(#)变化时,即会触发hashchange。锚点Hash起到引导浏览器将这次记录推入历史记录栈顶的作用,window.location对象处理“#”的改变并不会重新加载页面,而是将之当成新页面,放入历史栈里。并且,当前进或者后退或者触发hashchange事件时,我们可以在对应的事件处理函数中注册ajax等操作!
但是hashchange这个事件不是每个浏览器都有,低级浏览器需要用轮询检测URL是否在变化,来检测锚点的变化。当锚点内容(location.hash)被操作时,如果锚点内容发生改变浏览器才会将其放入历史栈中,如果锚点内容没发生变化,历史栈并不会增加,并且也不会触发hashchange事件。
16、介绍一下webpack和gulp,以及项目中具体的使用
17、你对es6的了解
参见阮大大的博客
http://es6.ruanyifeng.com/
18、解释一下vue和react,以及异同点
异同点:vue官网给过答案
https://cn.vuejs.org/v2/guide/comparison.html
只简单的用过vue,用vue写了一个日程表,请赐教哦~
https://yyywwwqqq.coding.me/schedule/dist/
源码地址:
https://coding.net/u/yyywwwqqq/p/schedule/git
19、关于平衡二叉树
平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是二叉搜索树,反之则不一定。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。
20、前后端分离的意义以及对前端工程化的理解
21、使用css实现一个三角形
利用border去画~
先看一下border的布局,如图:
WEB   试题 - 图17
所以三角形:
1.设置宽度、高度为0
WEB   试题 - 图18
2.不设置border-top
WEB   试题 - 图19
3.设置左右border颜色为transparent–透明
WEB   试题 - 图20
22、用promise手写ajax
function getJson(url){
return new Promise((resolve, reject) =>{
var xhr = new XMLHttpRequest();
xhr.open(‘open’, url, true);
xhr.onreadystatechange = function(){
if(this.readyState == 4){
if(this.status = 200){
resolve(this.responseText, this)
}else{
var resJson = { code: this.status, response: this.response }
reject(resJson, this)
}
}
}
xhr.send()
})
}

function postJSON(url, data) {
return new Promise( (resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open(“POST”, url, true)
xhr.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);

    xhr.onreadystatechange = function () {<br />            if (this.readyState === 4) {<br />                if (this.status === 200) {<br />                    resolve(JSON.parse(this.responseText), this)<br />                } else {<br />                    var resJson = { code: this.status, response: this.response }<br />                    reject(resJson, this)<br />                }<br />            }<br />        }

    xhr.send(JSON.stringify(data))<br />    })<br />}

getJSON(‘/api/v1/xxx’) // => 这里面是就try
.catch( error => {
// dosomething // => 这里就是catch到了error,如果处理error以及返还合适的值
})
.then( value => {
// dosomething // 这里就是final
})
23、手写一个类的继承,并解释一下
继承的形式有很多中,js高程里面归纳了其中,我简单说一下前三种。
1.原型继承
function Parent(){
this.name = “parent”;
}
Parent.prototype.getName = function(){
return this.name;
}

function Child(){
this.name = “child”;
}

//继承parent
Child.prototype = new Parent();
2.构造函数继承
function Animal(name){
this.name = name;
this.eat = function(){
consoel.log(this.name + “吃饭”);
}
}
var cat = new Animal(“maomi”);
cat.name;
cat.eat();
缺点是:
3.组合继承
24、解释一下call函数和apply函数的作用,以及用法
改变this的指向。
this的指向问题,在你不知道的js这本书中(神书)做了四点归纳:
1.默认绑定 (指 直接调用 foo(), this指向window)
2.隐式绑定(obj.foo(), this指向obj 这里会出现很多坑,下面的问题应该会有解答)
3.显示绑定(利用call、apply、bind改变this)
4.new(var cat = new Animal() , this指向cat对象)
25、你说自己抗压能力强,具体表现在哪里?

26、对前端前景的展望,以后前端会怎么发展
27、手写第一次面试没有写出来的链表问题,要求用es6写
28、平时是怎么学技术的?
29、平时大学里面时间是怎么规划的?
30、接下来有什么计划?这个学期和下个学期的计划是?
31、项目中遇到的难点,或者你学习路上的难点
32、你是通过什么方法和途径来学习前端的
33、手写一个简单遍历算法
34、解释一下react和vue,以及区别
35、你在团队中更倾向于什么角色?
36、对java的理解
37、介绍node.js,并且介绍你用它做的项目
38、手写一个js的深克隆
function deepCopy(obj){
//判断是否是简单数据类型,
if(typeof obj == “object”){
//复杂数据类型
var result = obj.constructor == Array ? [] : {};
for(let i in obj){
result[i] = typeof obj[i] == “object” ? deepCopy(obj[i]) : obj[i];
}
}else {
//简单数据类型 直接 == 赋值
var result = obj;
}
return result;
}
39、for函数里面setTimeout异步问题
40、手写归并排序
<1>.长度为n(n>1),把该输入序列分成两个长度为n/2的子序列;
<2>.对这两个子序列分别采用归并排序,直到长度n小于2;
<3>.将两个排序好的子序列合并成一个最终的排序序列。
function mergeSort(arr) {
var len = arr.length;
if(len < 2) {
return arr;
} else {
middle = Math.floor(len / 2);
var left = arr.slice(0, middle);
var right = arr.splice(middle);
return merge(mergeSort(left), mergeSort(right));
}

}

function merge(left, right) {
var result = [];
while(left.length && right.length) {
left[0] > right[0] ? result.push(right.shift()): result.push(left.shift());
}
if(left.length) {
result = result.concat(left);
}
if(right.length) {
result = result.concat(right);
}
return result;
}
41、介绍自己的项目

42、实现两个排序数组的合并
参考42题中的merge函数。
43、手写一个原生ajax
ajax:一种请求数据的方式,不需要刷新整个页面;
ajax的技术核心是 XMLHttpRequest 对象;
ajax 请求过程:创建 XMLHttpRequest 对象、连接服务器、发送请求、接收响应数据;
一个在stackoverflow的高分回答结合上面的代码,给出get和post的两种不同请求方法:
var ajax = {};
ajax.x = function () {
if (typeof XMLHttpRequest !== ‘undefined’) {
return new XMLHttpRequest();
}
var versions = [
“MSXML2.XmlHttp.6.0”,
“MSXML2.XmlHttp.5.0”,
“MSXML2.XmlHttp.4.0”,
“MSXML2.XmlHttp.3.0”,
“MSXML2.XmlHttp.2.0”,
“Microsoft.XmlHttp”
];

var xhr;<br />    for (var i = 0; i < versions.length; i++) {<br />        try {<br />            xhr = new ActiveXObject(versions[i]);<br />            break;<br />        } catch (e) {<br />        }<br />    }<br />    return xhr;<br />};

ajax.send = function (url, method, data, success,fail,async) {
if (async === undefined) {
async = true;
}
var x = ajax.x();
x.open(method, url, async);
x.onreadystatechange = function () {
if (x.readyState == 4) {
var status = x.status;
if (status >= 200 && status < 300) {
success && success(x.responseText,x.responseXML)
} else {
fail && fail(status);
}

    }<br />    };<br />    if (method == 'POST') {<br />        x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');<br />    }<br />    x.send(data)<br />};

ajax.get = function (url, data, callback, fail, async) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + ‘=’ + encodeURIComponent(data[key]));
}
ajax.send(url + (query.length ? ‘?’ + query.join(‘&’) : ‘’), ‘GET’, null, success, fail, async)
};

ajax.post = function (url, data, callback, fail, async) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + ‘=’ + encodeURIComponent(data[key]));
}
ajax.send(url,’POST’, query.join(‘&’), success, fail, async)
};
使用方法:GET
ajax.get(‘/test.php’, {foo: ‘bar’}, function(response,xml) {
//success
},
function(status){
//fail
});
POST
ajax.post(‘/test.php’, {foo: ‘bar’}, function(response,xml) {
//succcess

},function(status){
//fail

});
44、手写一个promise版的ajax
45、手写实现一个promise
46、手写实现requireJS模块实现
47、手写实现jquery里面的insertAfter
48、react和vue的介绍以及异同
49、AMD和CMD,commonJS的区别
50、介绍一下backbone
51、了解过SEO吗?
52、低版本浏览器不支持HTML5标签怎么解决?
53、用js使低版本浏览器支持HTML5标签 底层是怎么实现的?
54、实现一个布局:左边固定宽度为200,右边自适应,而且滚动条要自动选择只出现最高的那个
55、画出盒子模型,要使谷歌浏览器的盒子模型显示得跟IE浏览器一致(让谷歌跟ie一致,不是ie跟谷歌一致),该怎么做?
56、手写JS实现类继承,讲原型链原理,并解释new一个对象的过程都发生了什么
57、Array对象自带的方法,一一列举
58、若干个数字,怎么选出最大的五个
59、Array对象自带的排序函数底层是怎么实现的?
60、常用的排序算法有哪些,介绍一下选择排序
61、了解navigator对象吗?
62、手写一个正则表达式,验证邮箱
63、link和@import引入CSS的区别?
64、刚才说有些浏览器不兼容@import,具体指哪些浏览器?
65、介绍一下cookie,localstorage,sessionstorage,session
66、jquery绑定click的方法有几种
67、你的优点/竞争力
68、移动端适配问题
69、react的难点在哪里
70、做过css动画吗
71、如何优化网站
72、以后的规划
73、你做过最困难的事情是啥?
74、css3 html5新特性
75、闭包,ES6,跨域
76、问做过啥项目,用到什么技术,遇到什么困难
77、兼容性
78、盒子模型
79、Array的unshift() method的作用是什么?如何连接两个Array?如何在Array里移除一个元素?
80、用纸笔写一个Closure,任意形式和内容
81、知不知道Array-like Object?
82、如何用Native JavaScript来读写Cookie?
83、知不知道CSS Box-model?
84、如何做一个AJAX Request?
85、Cross-domain access有没有了解?
86、前端安全方面有没有了解?XSS和CSRF如何攻防?
87、HTTP Response的Header里面都有些啥?
88、知不知道HTTP2?
89、输入URL后发生了什么?
90、new operator实际上做了什么?
91、面向对象的属性有哪些?
92、做一个两栏布局,左边fixed width,右边responsive,用纸笔手写
93、讲一下AJAX Request
94、讲一下Cross-domain access
95、介绍一下做过的项目
96、问到了多个服务器怎么弄,架构之类的
97、angular的渲染流程
98、脏检查
99、nodejs的架构、优缺点、回调
100、css 盒模型
101、css 布局,左边定宽右边自适应
102、冒泡和捕获,事件流哪三个阶段?
103、实现事件代理
104、原型链
105、继承的两种方法
106、ajax,原生ajax的四个过程
107、闭包,简单说一个闭包的应用,然后闭包的主要作用是什么
108、css:两个块状元素上下的margin-top和margin-bottom会重叠。啥原因?怎么解决?
109、js:写一个递归。就是每隔5秒调用一个自身,一共100次
110、cookie和session有什么区别
111、网络分层结构
112、你的不足是什么?
113、做了那么多项目,有没有自己的归纳总结
114、工程怎么进行文件管理
115、less和sass掌握程度
116、Cookie 是否会被覆盖,localStorage是否会被覆盖
117、事件代理js实现
118、Css实现动画效果
119、Animation还有哪些其他属性
120、Css实现三列布局
121、Css实现保持长宽比1:1
122、Css实现两个自适应等宽元素中间空10个像素
123、requireJS的原理是什么
124、如何保持登录状态
125、浮动的原理以及如何清除浮动
126、Html的语义化
127、原生js添加class怎么添加,如果本身已经有class了,会不会覆盖,怎么保留?
128、Jsonp的原理。怎么去读取一个script里面的数据?
129、如果页面初始载入的时候把ajax请求返回的数据存在localStorage里面,然后每次调用的时候去localStorage里面取数,是否可行。
130、304是什么意思?有没有方法不请求不经过服务器直接使用缓存
131、http请求头有哪些字段
132、数组去除一个函数。用arr.splice。又问splice返回了什么?应该返回的是去除的元素。
133、js异步的方法(promise,generator,async)
134、Cookie跨域请求能不能带上
135、最近看什么开源项目?
136、commonJS和AMD
137、平时是怎么学习的?
138、为什么要用translate3d?
139、对象中key-value的value怎么再放一个对象?
140、Get和post的区别?
145、Post一个file的时候file放在哪的?
146、说说你对组件的理解
147、组件的html怎么进行管理
148、js的异步加载,promise的三种状态,ES7中的async用过么
149、静态属性怎么继承
150、js原型链的继承
151、jquery和zepto有什么区别
152、angular的双向绑定原理
153、angular和react的认识
154、MVVM是什么
155、移动端是指手机浏览器,还是native,还是hybrid
156、你用了移动端的什么库类和框架?
157、移动端要注意哪些?
158、适配有去考虑么,retina屏幕啊?
159、rem是什么?em是什么?如果上一层就是根root了,em和rem等价么?
160、怎么测试的?会自动化测试么?
161、你觉得你什么技术最擅长?
162、你平时有没有什么技术的沉淀?
163、单向链表怎么查找有没有环?
164、怎么得到一个页面的a标签?
165、怎么在页面里放置一个很简单的图标,不能用img和background-img?
166、正则表达式判断url
167、怎么去除字符串前后的空格
168、实现页面的局部刷新
169、绝对定位与相对定位的区别
170、js轮播实现思路
171、使用js画一个抛物线,抛物线上有个小球随着抛物线运动,有两个按钮能使小球继续运动停止运动
172、java五子棋,说下实现思路
173、如何让各种情况下的div居中(绝对定位的div,垂直居中,水平居中)?
174、display有哪些值?说明他们的作用
175、css定义的权重
176、requirejs实现原理
177、requirejs怎么防止重复加载
178、ES6里头的箭头函数的this对象与其他的有啥区别
179、tcp/udp区别
180、tcp三次握手过程
181、xss与csrf的原理与怎么防范
182、mysql与 MongoDB的区别
183、w3c事件与IE事件的区别
184、有没有上传过些什么npm模块
185、IE与W3C怎么阻止事件的冒泡
186、gulp底层实现原理
187、webpack底层实现原理
188、gulp与webpack区别
189、vuejs与angularjs的区别
190、vuex是用来做什么的
191、说下你知道的响应状态码
192、ajax的过程以及 readyState几个状态的含义
193、你除了前端之外还会些什么?
194、cookie与session的区别
195、一些关于php与java的问题
196、你觉得你哪个项目是你做的最好的
197、说说你在项目中遇到了哪些困难,是怎么解决的
198、前端优化你知道哪些
199、webpack是用来干嘛的
200、webpack与gulp的区别
201、es6与es7了解多少
202、说下你知道的响应状态码
203、看过哪些框架的源码
204、遇到过哪些浏览器兼容性问题
205、清除浮动有哪几种方式,分别说说
206、你知道有哪些跨域方式,分别说说
207、JavaScript有哪几种类型的值
208、使用 new操作符时具体是干了些什么
209、学习前端的方法以及途径
210、怎么实现两个大整数的相乘,说下思路
211、你学过数据结构没,说说你都了解些什么
212、你学过计算机操作系统没,说说你都了解些什么
213、你学过计算机组成原理没,说说你都了解些什么
214、你学过算法没,说说你都了解些什么
215、说下选择排序,冒泡排序的实现思路
216、用过哪些框架
217、让你设计一个前端css框架你怎么做
218、了解哪些设计模式说说看
219、说下你所了解的设计模式的优点
220、vue源码结构
221、状态码
222、浏览器缓存的区别
223、304与200读取缓存的区别
224、http请求头有哪些,说说看你了解哪些
225、js中this的作用
226、js中上下文是什么
227、js有哪些函数能改变上下文
228、你所了解的跨域的方法都说说看你了解的?
229、要是让你自己写一个js框架你会用到哪些设计模式
230、平常在项目中用到过哪些设计模式,说说看
231、一来给了张纸要求写js自定义事件
232、前端跨域的方法
233、call与apply的区别
234、h5有个api能定位你知道是哪个吗?
235、vue与angularjs中双向数据绑定是怎样实现的?
236、webpack怎样配置?
237、nodejs中的文件怎么读写?
238、link和@import有什么区别?
239、cookies,sessionStorage 和 localStorage 的区别
240、看过哪些前端的书?平时是怎么学习的
241、说下你所理解的mvc与mvvc
242、position有哪些值,说下各自的作用
243、写个从几个li中取下标的闭包代码
244、你的职业规划是怎么样的?
245、移动端性能优化
246、lazyload如何实现
247、点透问题
248、前端安全
249、原生js模板引擎
250、repaint和reflow区别
251、requirejs如何避免循环依赖?
252、实现布局:左边一张图片,右边一段文字(不是环绕)
253、window.onload和$(document).ready()的区别,浏览器加载转圈结束时哪个时间点?
254、form表单当前页面无刷新提交 target iframe
255、setTimeout和setInterval区别,如何互相实现?
256、如何避免多重回调—promise,promise简单描述一下,如何在外部进行resolve()
257、margin坍塌?水平方向会不会坍塌?
258、伪类和伪元素区别
259、vue如何实现父子组件通信,以及非父子组件通信
260、数组去重
261、使用flex布局实现三等分,左右两个元素分别贴到左边和右边,垂直居中

Web前端笔试115道题(带答案及解析)

文章标签: 前端 面试题
1、html5为什么只需要写<!doctype html>?
答:html5不是基于sgml(标准通用标记语言),不需要对dtd文件进行引用,但是需要doctype来规范浏览器的行为,
否则浏览器将开启怪异模式,而html4.01基于sgml,需要引入dtd,才能告知浏览器文档使用的文档类型
2、行内元素有哪些?块级元素有哪些?空(void)元素有哪些?
行内元素有:a b span img input select strong(强调的语气)
块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
知名的空元素:


WEB   试题 - 图21
鲜为人知的是:

3、页面导入样式时,使用link和@import有什么区别?
两者都是外部引用CSS的方式,但是存在一定的区别:
  区别1:link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
  区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
  区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
  区别4:link支持使用Javascript控制DOM去改变样式;而@import不支持。
补充:@import最优写法
@import的写法一般有下列几种:
@import ‘style.css’ //Windows IE4/ NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import “style.css” //Windows IE4/ NS4, Macintosh IE4/NS4不识别
@import url(style.css) //Windows NS4, Macintosh NS4不识别
@import url(‘style.css’) //Windows NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import url(“style.css”) //Windows NS4, Macintosh NS4不识别
由上分析知道,@import url(style.css) 和@import url(“style.css”)是最优的选择,兼容的浏览器最多。
从字节优化的角度来看@import url(style.css)最值得推荐。
4、常见的浏览器内核有哪些?
使用Trident内核的浏览器:IE、Maxthon、TT、The World等;
使用Gecko内核的浏览器:Netcape6及以上版本、FireFox、MozillaSuite/SeaMonkey;
使用Presto内核的浏览器:Opera7及以上版本;
使用Webkit内核的浏览器:Safari、Chrome。
5、html5有哪些新特性?移除了哪些元素?如何处理HTML5新标签的浏览器兼容性问题?如何区分html和html5?
新增的元素有绘画 canvas ,用于媒介回放的 video 和 audio 元素,本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失,而sessionStorage的数据在浏览器关闭后自动删除,此外,还新增了以下的几大类元素。
内容元素,article、footer、header、nav、section。
表单控件,calendar、date、time、email、url、search。
控件元素,webworker, websockt, Geolocation。
移出的元素有下列这些:
显现层元素:basefont,big,center,font, s,strike,tt,u。
性能较差元素:frame,frameset,noframes。

如何处理HTML5新标签的浏览器兼容问题?如何区分HTML和HTML5?
处理兼容问题有两种方式:
1.IE8/IE7/IE6支持通过document.方法产生的标签,利用这一特性让这些浏览器支持HTML5新标签。
2.使用是html5shim框架
另外,DOCTYPE声明的方式是区分HTML和HTML5标志的一个重要因素,此外,还可以根据新增的结构、功能元素来加以区分。

6、iframe有哪些优缺点?
优点:
1.用来实现长连接,在websocket不可用的时候作为一种替代,最开始由google发明。Comet:基于 HTTP 长连接的”服务器推”技术
2.跨域通信。JavaScript跨域总结与解决办法 ,类似的还有浏览器多页面通信,比如音乐播放器,用户如果打开了多个tab页,应该只有一个在播放。
3.历史记录管理,解决ajax化网站响应浏览器前进后退按钮的方案,在html5的history api不可用时作为一种替代。
4.纯前端的utf8和gbk编码互转。比如在utf8页面需要生成一个gbk的encodeURIComponent字符串,可以通过页面加载一个gbk的iframe,然后主页面与子页面通信的方式实现转换,这样就不用在页面上插入一个非常巨大的编码映射表文件了
缺点:
 1、在网页中使用框架结构最大的弊病是搜索引擎的”蜘蛛”程序无法解读这种页面。当”蜘蛛”程序遇到由数个框架组成的网页时,它们只看到框架而 无法找到链接,因此它们会以为该网站是个死站点,并且很快转身离去。对一个网站来说这无异于一场灾难。
  如果你想销售产品,你需要客户;如想得到客户,你首先要让人们访问你的网站,而要做到这一点,你就非求助于搜索引擎不可。你花费了大量的时间、 精力和金钱开设了一家网上商店,却又故意不让搜索引擎检索你,这就好象开家零售商店,却将窗户全部漆成黑色,而且还不挂任何招牌一样。

  2、框架结构有时会让人感到迷惑,特别是在几个框架中都出现上下、左右滚动条的时候。这些滚动条除了会挤占已经非常有限的页面空间外,还会分散 访问者的注意力。访问者遇到这种网站往往会立刻转身离开。他们会想,既然你的主页如此混乱,那么网站的其他部分也许更不值得浏览。
  3、链接导航问题。使用框架结构时,你必须保证正确设置所有的导航链接,如不然,会给访问者带来很大的麻烦。比如被链接的页面出现在导航框架 内,这种情况下访问者便被陷住了,因为此时他没有其他地方可去。
7、label的作用是什么?是怎么使用的?
Label 中有两个属性是非常有用的,一个是FOR、另外一个就是ACCESSKEY了。
FOR属性
功能:表示Label标签要绑定的HTML元素,你点击这个标签的时候,所绑定的元素将获取焦点。
用法:
ACCESSKEY属性:
功能:表示访问Label标签所绑定的元素的热键,当您按下热键,所绑定的元素将获取焦点。
用法:
局限性:accessKey属性所设置的快捷键不能与浏览器的快捷键冲突,否则将优先激活浏览器的快捷键。
8、实现不使用border,画出1px高的线,在不同浏览器下的Quirksmode和CSSCompat模式下都能保持一致的效果?

9、网页验证码是干嘛的?是为了解决什么安全问题?
网页验证码介绍:”验证码”的英文表示为CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart),翻译过来就是”全自动区分计算机和人类的图灵测试”,顾名思义,它是用来区分计算机和人类的。在 CAPTCHA 测试中,作为服务器的计算机会自动生成一个问题由用户来解答。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答 CAPTCHA 的问题,所以回答出问题的用户就可以被认为是人类。 CAPTCHA 是由计算机来考人类,而不是标准图灵测试中那样由人类来考计算机,因此人们有时称 CAPTCHA 是一种反向图灵测试。
验证码的原理:服务器端随机生成验证码字符串,保存在内存中,并写入图片,发送给浏览器端显示,浏览器端输入验证码图片上字符,然后提交服务器端,提交的字符和服务器端保存的该字符比较是否一致,一致就继续,否则返回提示。攻击者编写的robot程序,很难识别验证码字符,顺利的完成自动注册,登录;而用户可以识别填写,所以这就实现了阻挡攻击的作用。而图片的字符识别,就是看图片上的干扰强度了。就实际的效果来说,验证码只是增加攻击者的难度,而不可能完全的防止。
10、介绍一下标准的css的盒子模型?与低版本IE的盒子模型有什么不同?
盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型
W3C 盒子模型的范围包括 margin、border、padding、content,并且 content 部分不包含其他部分
IE 盒子模型的范围也包括 margin、border、padding、content,和标准 W3C 盒子模型不同的是:IE 盒子模型的 content 部分包含了 border 和 pading
11、如何居中div,如何居中一个浮动元素?如何让绝对定位的div居中?
a.margin:xpx auto;
b.确定容器的宽高,这里宽度是必须的,高度可以不设,设置外层的上外边距和左外边距分别是宽高的一半。
实现居中关键在于 margin设置与 position:relative.
.div {
width:500px ;
height:300px;
margin: -150px 0 0 -250px;
position:relative;
left:50%;
top:50%;
}
c.position:absolute;
top: 50%;
left: 50%; 只能把div定位在以红色圈为起点的位置,加上margin:-100px 0px 0px -100
12、display有哪些值?说明他们的作用?
block :块对象的默认值。用该值为对象之后添加新行
none :隐藏对象。与visibility属性的hidden值不同,其不为被隐藏的对象保留其物理空间
inline :内联对象的默认值。用该值将从对象中删除行
compact :分配对象为块对象或基于内容之上的内联对象
marker :指定内容在容器对象之前或之后。要使用此参数,对象必须和:after及:before 伪元素一起使用
inline-table :将表格显示为无前后换行的内联对象或内联容器
list-item :将块对象指定为列表项目。并可以添加可选项目标志
run-in :分配对象为块对象或基于内容之上的内联对象
table :将对象作为块元素级的表格显示
13、position的值relative和absolute的定位原点是什么?
Absolute,CSS中的写法是:position:absolute; 他的意思是绝对定位,他是参照浏览器的左上角,配合TOP、RIGHT、BOTTOM、LEFT(下面简称TRBL)进行定位,在没有设定TRBL,默认依据父级的做标原始点为原始点。如果设定TRBL并且父级没有设定position属性,那么当前的absolute则以浏览器左上角为原始点进行定位,位置将由TRBL决定。

Relative,CSS中的写法是:position:relative; 他的意思是绝对相对定位,他是参照父级的原始点为原始点,无父级则以BODY的原始点为原始点,配合TRBL进行定位,当父级内有padding等CSS属性时,当前级的原始点则参照父级内容区的原始点进行定位。

14、display设置为inline-block时,li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
行框的排列会受到中间空白(回车空格等等)的影响,这些空白也会被应用样式,占据空间,所以会有间隔
解决:设置ul的font-size为0,缺陷是必须重新在li中去设置字体大小

15、请解释下为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?
a.添加新的元素 、应用 clear:both;
b.父级定义 overflow: auto(注意:是父级div也就是这里的 div.outer) 一个对seo比较友好,另个hidden对seo不是太友好
在IE6中还需要触发 hasLayout ,例如 zoom:1;
c.据说是最高大上的方法 :after
方法:(注意:作用于浮动元素的父亲)IE6-7不支持:after,
使用 zoom:1触发 hasLayout
{zoom:1;} /==for IE6/7 Maxthon2==/
:after {clear:both;content:’.’;display:block;width: 0;height: 0;visibility:hidden;}
d.使用 br标签和其自身的 html属性,
clear=”all | left | right | none” 属性
e.父元素也设置浮动
f.父元素设置display:table 盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用
16、在网页中的应该使用奇数还是偶数的字体?为什么呢?
偶数字号相对更容易和 web 设计的其他部分构成比例关系
使用奇数号字体不好的地方是,文本段落无法对齐
17、margin和padding分别适合什么场景使用?
何时应当使用margin:
(1)需要在border外侧添加空白时,
(2)空白处不需要有背景(色)时,
(3)上下相连的两个盒子之间的空白需要相互抵消时,比如15px+20px的margin,将得到20px的空白(注意地方见第三点)。
何时应当使用padding
(1)需要在border内侧添加空白时(往往是文字与边框距离的设置),
(2)空白处需要背景(色)时,
(3)上下相连的两个盒子之间的空白希望等于两者之和时,比如15px+20px的padding,将得到35px的空白。
margin使用时应该注意的地方
margin在垂直方向上相邻的值相同时会发生叠加,水平方向上相邻的值会相加。margin取负值时,在垂直方向上,两个元素的边界仍然会重叠。但是,此时一个为正值,一个为负值,并不是取其中较大的值,而是用正边界减去负边界的绝对值,也就是说,把正的边界值和负的边界值相加。
18、元素竖向的百分比设定是相对于容器的高度吗?
答:相对于父容器的宽度
19、什么是响应式设计?响应式设计的基本原理是什么?如何兼容较低版本的IE?
答:一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。
优点:
面对不同分辨率设备灵活性强
能够快捷解决多设备显示适应问题
缺点:
兼容各种设备工作量大,效率低下
代码累赘,会出现隐藏无用的元素,加载时间加长
其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果
一定程度上改变了网站原有的布局结构,会出现用户混淆的情况
respond.js和css3-mediaqueries-js
20、设置元素浮动后,该元素的display值是多少?
display:block;
21、怎么让chrome支持小于12px的文字?
chrome私有属性:-webkit-text-size-adjust:none;
-webkit-transform:scale(0.8);
行内元素设置:-webkit-transform:scale(0.8);display:inline-block
22、display:inline-block什么时候会显示间隙?
1.给 父元素 写font-size:0
2.把标签写到一行,不要在编辑器里敲回车换行,但是这种写法对于标签很多的情况可读性太差,适用与例如这样简单的结构
23、有一个高度自适应的div。里面有2个div,一个高度100px,希望另一个填满剩下的高度?
外层box-sizing: border-box; 同时设置padding: 100px 0 0;
内层100像素高的元素向上移动100像素,或使用absolute定位防止占据空间;
另一个元素直接height: 100%;
外层position: relative;
百分百自适应元素直接position: absolute; top: 100px; bottom: 0; left: 0
24、什么是window对象?什么是document对象?
window它是一个顶层对象,而不是另一个对象的属性即浏览器的窗口。
document对象是window对象的一个对象属性
25、null和undefined的区别?
null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN。
null表示”没有对象”,即该处不应该有值
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
26、什么是闭包(closure)?为什么要用它?
闭包就是能够读取其他函数内部变量的函数
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的用途:
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中
重用变量又不能造成全局污染
27、js代码中”use strict”是什么意思?使用它区别是什么?
进入”严格模式”的标志,老版本的浏览器会把它当作一行普通字符串,加以忽略
将”use strict”放在脚本文件的第一行,则整个脚本都将以”严格模式”运行。如果这行语句不在第一行,则无效,整个脚本以”正常模式”运行。如果不同模式的代码文件合并成一个文件,这一点需要特别注意。
(严格地说,只要前面不是产生实际运行结果的语句,”use strict”可以不在第一行,比如直接跟在一个空的分号后面。)
将”use strict”放在函数体的第一行,则整个函数以”严格模式”运行
因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中
– 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
– 消除代码运行的一些不安全之处,保证代码运行的安全;
– 提高编译器效率,增加运行速度;
– 为未来新版本的Javascript做好铺垫。
28、js中有一个函数,执行对象查找时,永远不会去查找原型,这个函数是什么?
hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性。如果有,返回true,否则返回false。该方法属于Object对象,由于所有的对象都”继承”了Object的对象实例,因此几乎所有的实例对象都可以使用该方法。
29、js延迟加载的方式有哪些?
js的延迟加载有助与提高页面的加载速度,以下是延迟加载的几种方法:
1.使用setTimeout延迟方法的加载时间
延迟加载js代码,给网页加载留出更多时间

2.让js最后加载
例如引入外部js脚本文件时,如果放入html的head中,则页面加载前该js脚本就会被加载入页面,而放入body中,则会按照页面从上倒下的加载顺序来运行JavaScript的代码~~~ 所以我们可以把js外部引入的文件放到页面底部,来让js最后引入,从而加快页面加载速度

3.上述方法2也会偶尔让你收到Google页面速度测试工具的”延迟加载javascript”警告。所以这里的解决方案将是来自Google帮助页面的推荐方案。
//这些代码应被放置在标签前(接近HTML文件底部)


这段代码意思是等到整个文档加载完后,再加载外部文件”defer.js”。
使用此段代码的步骤:
1).复制上面代码
2).粘贴代码到HTML的标签前 (靠近HTML文件底部)
3).修改”defer.js”为你的外部JS文件名
4).确保你文件路径是正确的。例如:如果你仅输入”defer.js”,那么”defer.js”文件一定与HTML文件在同一文件夹下。

注意:这段代码直到文档加载完才会加载指定的外部js文件。因此,不应该把那些页面正常加载需要依赖的javascript代码放在这里。而应该将JavaScript代码分成两组。一组是因页面需要而立即加载的javascript代码,另外一组是在页面加载后进行操作的javascript代码(例如添加click事件或其他东西)。这些需等到页面加载后再执行的JavaScript代码,应放在一个外部文件,然后再引进来。
30、同步和异步的区别?
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
举个浏览器例子:普通B/S模式(同步)AJAX技术(异步)
同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕
再举个生活的例子:大家联系的时候如果使用手机通话,那么只能跟一个人联系,过程中做不了其他任何操作,如果使用短信或者聊天的方式,就可以同时跟很多人聊天,别人收到信息后会回复,在回复之前还可以跟另外的人进行聊天。

31、document.write和innerHTML的区别?
1.document.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open。每次写完关闭之后重新调用该函数,会导致页面被重写。
2.innerHTML则是DOM页面元素的一个属性,代表该元素的html内容。你可以精确到某一个具体的元素来进行更改。如果想修改document的内容,则需要修改document.documentElement.innerElement。
3.两者都可动态包含外部资源如JavaScript文件
通过document.write插入元素会自动执行其中的脚本;
大多数浏览器中,通过innerHTML插入元素并不会执行其中的脚本
innerHTML很多情况下都优于document.write,其原因在于其允许更精确的控制要刷新页面的那一个部分。
32、.call()和.apply()的含义和区别?
1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为方法的属性,那它们的使用就当然是针对方法的了,这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同。
2、语法:foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments) == this.foo(arg1, arg2, arg3);
3、相同点:两个方法产生的作用是完全一样的。
4、不同点:方法传递的参数不同,单个单数传入,另一个可以以数组方式传入

33、JQ和JQUI有啥区别?

jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是”write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery UI 是建立在 jQuery JavaScript 库上的一组用户界面交互、特效、小部件及主题。
34、需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器的前进,后退时正确响应。给出你的技术实现方案?
用cookie或者localStorage来记录应用的状态即可,刷新页面时读取一下这个状态,然后发送相应ajax请求来改变页面即可
HTML5里引用了新的API,就是history.pushState和history.replaceState,就是通过这个接口做到无刷新改变页面URL的
虽然ajax可以无刷新改变页面内容,但无法改变页面URL
其次为了更好的可访问性,内容发生改变后,改变URL的hash。但是hash的方式不能很好的处理浏览器的前进、后退等问题
有的浏览器引入了onhashchange的接口,不支持的浏览器只能定时去判断hash是否改变
再有,ajax的使用对搜索引擎很不友好,往往蜘蛛爬到的区域是空的
为了解决传统ajax带来的问题,HTML5里引入了新的API,即:history.pushState, history.replaceState
可以通过pushState和replaceState接口操作浏览器历史,并且改变当前页面的URL。
pushState是将指定的URL添加到浏览器历史里,replaceState是将指定的URL替换当前的URL。
如何调用
var state = { title: title, url: options.url, otherkey: othervalue};window.history.pushState(state, document.title, url);
state对象除了要title和url之外,也可以添加其他的数据,比如:还想将一些发送ajax的配置给保存起来。
replaceState和pushState是相似的,不需要多做解释。
如何响应浏览器的前进、后退操作
window对象上提供了onpopstate事件,上面传递的state对象会成为event的子对象,这样就可以拿到存储的title和URL了。
window.addEventListener(‘popstate’, function(e){ if (history.state){ var state = e.state; //do something(state.url, state.title); }}, false);
这样就可以结合ajax和pushState完美的进行无刷新浏览了。
35、js的数据类型都有哪些?
字符串、数字、布尔、数组、对象、Null、Undefined
36、已知ID的input输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)
document.getElementById(id).value;
37、希望获取到页面中所有的checkbox怎么做?(不使用第三方框架)
document.getElementsByTagName(‘input’);
遍历循环
38、设置一个已知ID的div和html内容为xxx,字体颜色设置为黑色?(不使用第三方框架)
var div = document.getElementById(id);
div.innerHTML = ”;
div.style.color = ”;
39、当一个dom节点被点击时,我们需要能够执行一个函数,应该怎么做?
直接在DOM里绑定事件:”

xx
” …
在JS里通过onclick绑定:xxx.onclick = test
通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)
  那么问题来了,Javascript的事件流模型都有什么?
“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
40、什么是Ajax和JSON,他们的优缺点?
Ajax是异步JavaScript和XML,用于在Web页面中实现异步数据交互。
  优点:
可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量
避免用户不断刷新或者跳转页面,提高用户体验
缺点:
对搜索引擎不友好(
要实现ajax下的前后退功能成本较大
可能造成请求数的增加
跨域问题限制
JSON是一种轻量级的数据交换格式,ECMA的一个子集
  优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)
41、请看下列代码输出什么?解释原因?
var a;
alert(typeof a); //undefined
alert(b); //报错
解释:Undefined是一个只有一个值的数据类型,这个值就是”undefined”,
在使用var声明变量但并未对其赋值进行初始化时,这个变量的值就是undefined。而b由于未声明将报错。
注意未申明的变量和声明了未赋值的是不一样的。
ar a = null;
alert(typeof a); //object
  解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,所以用typeof检测会返回”object”

42、js的typeof返回哪些数据类型?
有如下6种返回值:
1)number;
2)string;
3)boolean;
4)object
5)function
6)undefined;
43、split() join()的区别?
join() 方法用于把数组中的所有元素放入一个字符串。
元素是通过指定的分隔符进行分隔的。
指定分隔符方法join(“#”);其中#可以是任意
与之相反的是split()方法:用于把一个字符串分割成字符串数组.
44、数组方法pop() push() unshift() shift()?
push和pop方法,这两个方法只会对数组从尾部进行压入或弹出,而且是在原数组进行操作,任何的改动都是会影响到操作的数组。push(args)可以每次压入多个元素,并返回更新后的数组长度。pop()函数每次只会弹出最后一个结尾的元素,并返回弹出的元素,如果是对空组数调用pop()则返回undefined。 如果参数是数组则是将整个数组当做一个元素压入到原来的数组当中。并不会产生类似concat合并数组时产生的”拆分现象”
unshift和shift这两个方法都是通过对数组的头部进行的操作,其他基本跟push和pop类似
shift:从集合中把第一个元素删除,并返回这个元素的值。
unshift: 在集合开头添加一个或更多元素,并返回新的长度
push:在集合中添加元素,并返回新的长度
pop:从集合中把最后一个元素删除,并返回这个元素的值
45、ajax请求时,如何解释json数据?
1.$.JSON(url,params,fun);
2.$.ajax({}); dataType:’json’
都可以使用$each();进行遍历
$.each(object,function(index,item){
});
46、js的本地对象,内置对象和宿主对象?
本地对象:
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError官方定义好了的对象
内置对象: Global 和 Math,内置对象是本地对象的一种
宿主对象:所有的BOM和DOM对象都是宿主对象,是那些官方未定义,你自己构建的对象加上DOM和BOM对象组成的
47、列举所了解的前端框架并简述?
以下是常用的前端基础框架:

以下是常见的前端构建框架:

以下是场检的JS/CSS模块化开发的框架:

48、对web标准以及w3c的理解与认识?
(1)web标准规范要求,书写标签必须闭合、标签小写、不乱嵌套,可提高搜索机器人对网页内容的搜索几率。— SEO
(2)建议使用外链css和js脚本,从而达到结构与行为、结构与表现的分离,提高页面的渲染速度,能更快地显示页面的内容。
(3)样式与标签的分离,更合理的语义化标签,使内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件, 从而降低维护成本、改版更方便
(4)不需要变动页面内容,便可提供打印版本而不需要复制内容,提高网站易用性
遵循w3c制定的web标准,能够使用户浏览者更方便的阅读,使网页开发者之间更好的交流。
49、xhtml和html有什么区别?
XHTML是HTML 4.01和XML1.0的杂交,XHTML1.0是基于HTML4.01的
HTML是一种基于标准通用标记语言(SGML)的应用,而XHTML则基于可扩展标记语言(XML),HTML和XHTML其实是平行发展的两个标准。本质上说,XHTML是一个过渡技术,结合了部分XML的强大功能及大多数HTML的简单特性。建立XHTML的目的就是实现HTML向XML的过渡
1、XHTML要求正确嵌套
2、XHTML所有元素必须关闭
3、XHTML区分大小写
4、XHTML属性值要加引号
5、XHTML用id属性代替name属性
6、属性值不能简写
50、行内元素有哪些?块级元素有哪些?css和盒子模型?
盒子模型:内容、填充(padding)、边框(border)、外边界(margin)
box-sizing:border-box; box-sizing:content-box;
51、css选择器有哪些?哪些属性可以继承?优先级算法如何计算?内联和import哪个级别更高?
可继承的:font-size font-family color
不可继承的:border padding margin background-color width height
优先级:!important > [ id > class > tag ] important 比 内联优先级高
52、前端页面有哪三层构成,分别是什么?作用是什么?
结构层、表示层、行为层
结构层(structural layer)
由 HTML 或 XHTML之类的标记语言负责创建。标签,也就是那些出现在尖括号里的单词,对网页内容的语义含义做出了描述,但这些标签不包含任何关于如何显示有关内容的信息。例如,P标签表达了这样一种语义:”这是一个文本段。”
表示层(presentation layer)
由 CSS 负责创建。 CSS对”如何显示有关内容”的问题做出了回答。
行为层(behaviorlayer)
负责回答”内容应该如何对事件做出反应”这一问题。这是 Javascript 语言和 DOM主宰的领域
53、你如何对网站的文件和资源进行优化?期待的解决方法包括?
A、文件合并,减少http请求,合并JavaScript和CSS文件、CSS Sprites、图像映射 (Image Map)和使用Data URI来编码图片
B、文件最小化/文件压缩,减少文件下载的体积;常用的工具是YUI Compressor
C、使用 CDN 托管,尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定
D、缓存的使用(多个域名来提供缓存)
E、GZIP 压缩你的 JS 和 CSS 文件

54、看下列代码?输出什么?解释原因?
var a = null;
alert(typeof a);
答案:输出为object, JS类型值是存在32 BIT 单元里,32位有1-3位表示TYPE TAG,其它位表示真实值
而表示object的标记位正好是低三位都是0
000: object. The data is a reference to an object.
而js 里的Null 是机器码NULL空指针, (0x00 is most platforms).所以空指针引用 加上 对象标记还是0,最终体现的类型还是object..
这也就是为什么Number(null)===0吧…
The history of “typeof null”
2. 曾经有提案 typeof null === ‘null’.但提案被拒绝
harmony:typeofnull
55、看代码给答案?并进行解释?
var a = new Object();
a.value=1;
b = a;
b.value=2;
alert(a.value);
56、var numberArray = [3,6,2,4,1,5];
1) 实现对该数组的倒排,输出[5,1,4,2,6,3]
  2) 实现对该数组的降序排列,输出[6,5,4,3,2,1]
var numberArray = [3,6,2,4,1,5];
numberArray.reverse(); // 5,1,4,2,6,3
numberArray.sort(function(a,b){ //6,5,4,3,2,1
return b-a;
})
57、你能描述一下渐进增强和优雅降级之间的不同吗?
如果提到了特性检测,可以加分。
检测浏览器,渐进增强就是让牛b的浏览器的效果更好,优雅降级就是让2b的浏览器在功能ok的情况下效果一般。
58、线程与进程的区别?
一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

59、请解释一下什么是”语义化的 HTML”?
语义化的好处:
1:去掉或样式丢失的时候能让页面呈现清晰的结构:
html本身是没有表现的,我们看到例如

是粗体,字体大小2em,加粗;是加粗的,不要认为这是html的表现,这些其实html默认的css样式在起作用,所以去掉或样式丢失的时候能让页面呈现清晰的结构不是
的HTML结构的优点,但是浏览器都有有默认样式,默认样式的目的也是为了更好的表达html的语义,可以说浏览器的默认样式和语义化的HTML结构是不可分割的。
2.屏幕阅读器(如果访客有视障)会完全根据你的标记来”读”你的网页.
3.PDA、手机等设备可能无法像普通电脑的浏览器一样来渲染网页(通常是因为这些设备对CSS的支持较弱).
4.搜索引擎的爬虫也依赖于标记来确定上下文和各个关键字的权重.
5.你的页面是否对爬虫容易理解非常重要,因为爬虫很大程度上会忽略用于表现的标记, 而只注重语义标记.
6.便于团队开发和维护
语义化的HTML就是:标题用h1-h6,文字段落用p,列表用ul li,大致如此

60、为什么利用多个域名来提供网站资源会更有效?
浏览器同一时间可以从一个域名下载多少资源?你的浏览器能同时保持对一个域名的多少连接?
三个最主流的原因:
1. CDN缓存更方便
2. 突破浏览器并发限制 (你随便挑一个 G家的 url: https://lh4.googleusercontent.com/- si4dh2myPWk/T81YkSi__AI/AAAAAAAAQ5o/LlwbBRpp58Q/w497-h373/IMG_20120603_163233.jpg, 把前面的 lh4换成 lh3,lh6 啥的,都照样能够访问,像地图之类的需要大量并发下载图片的站点,这个非常重要。)
3. Cookieless, 节省带宽,尤其是上行带宽 一般比下行要慢。。。
还有另外两个非常规原因:
4. 对于UGC的内容和主站隔离,防止不必要的安全问题( 上传js窃取主站cookie之类的) 。
正是这个原因要求用户内容的域名必须不是自己主站的子域名,而是一个完全独立的第三方域名。
5. 数据做了划分,甚至切到了不同的物理集群,通过子域名来分流比较省事. ^
^ 这个可能被用的不多。
PS: 关于Cookie的问题,带宽是次要的,安全隔离才是主要的。
关于多域名,也不是越多越好,虽然服务器端可以做泛解释,浏览器做dns解释也是耗时间的,而且太多域名,如果要走 https的话,还有要多买证书和部署的问题,^^。

61、请说出三种减少页面加载时间的方法。(加载时间指感知的时间或者实际加载时间)
1.优化图片
2.图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)
3.优化CSS(压缩合并css,如margin-top,margin-left…)
4.网址后加斜杠(如www.campr.com/目录,会判断这个”目录是什么文件类型,或者是目录。)
5.标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。
当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了。)
6.减少http请求(合并文件,合并图片)。

62、如果你参与到一个项目中,发现他们使用 Tab 来缩进代码,但是你喜欢空格,你会怎么做?
1.建议这个项目使用像 EditorConfig (http://editorconfig.org/) 之类的规范
2.为了保持一致性,接受项目原有的风格
3.直接使用 VIM 的 retab 命令

63、请写一个简单的幻灯效果页面
如果不使用JS来完成,可以加分。(如:纯CSS实现的幻灯片效果)
可以采用CSS3的单选按钮radio来实现图片的切换
64、你都使用哪些工具来测试代码的性能?
Profiler, JSPerf(http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout), Dromaeo

65、如果今年你打算熟练掌握一项新技术,那会是什么?
nodejs,html5,css3,less

66、请谈一下你对网页标准和标准制定机构重要性的理解?
(google)w3c存在的意义就是让浏览器兼容性问题尽量小,首先是他们对浏览器开发者的约束,然后是对开发者的约束。

67、什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?
FOUC – Flash Of Unstyled Content 文档样式闪烁

而引用CSS文件的@import就是造成这个问题的罪魁祸首。IE会先加载整个HTML文档的DOM,然后再去导入外部的CSS文件,因此,在页面DOM加载完成到CSS导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。
解决方法简单的出奇,只要在之间加入一个或者元素就可以了。

68、doctype(文档类型)的作用是什么?你知道多少种文档类型?
此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范。
该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。
HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。
XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。
Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks
(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。

69、浏览器标准模式和怪异模式之间的区别是什么?
W3C标准推出以后,浏览器都开始采纳新标准,但存在一个问题就是如何保证旧的网页还能继续浏览,在标准出来以前,很多页面都是根据旧的渲染方法编写的,如果用的标准来渲染,将导致页面显示异常。为保持浏览器渲染的兼容性,使以前的页面能够正常浏览,浏览器都保留了旧的渲染方法(如:微软的IE)。这样浏览器渲染上就产生了Quircks mode和Standars mode,两种渲染方法共存在一个浏览器上。

IE盒子模型和标准W3C盒子模型:ie的width包括:padding\border。 标准的width不包括:padding\border
在js中如何判断当前浏览器正在以何种方式解析?
document对象有个属性compatMode ,它有两个值:
BackCompat 对应quirks mode
CSS1Compat 对应strict mode

70、使用 XHTML 的局限有哪些?
xhtml要求严格,必须有head、body每个dom必须要闭合。
如果页面使用’application/xhtml+xml’会有什么问题吗?
一些老的浏览器并不兼容。
十六、如果网页内容需要支持多语言,你会怎么做?
编码UTF-8,空间域名需要支持多浏览地址。
在设计和开发多语言网站时,有哪些问题你必须要考虑?
1、应用字符集的选择 2、语言书写习惯&导航结构 3、数据库驱动型网站

71、data-属性的作用是什么?
data-为前端开发者提供自定义的属性,这些属性集可以通过对象的dataset属性获取,不支持该属性的浏览器可以通过 getAttribute方法获取

div.dataset.commentNum; // 10

需要注意的是,data-之后的以连字符分割的多个单词组成的属性,获取的时候使用驼峰风格。
并不是所有的浏览器都支持.dataset属性,测试的浏览器中只有Chrome和Opera支持。

72、如果把 HTML5 看作做一个开放平台,那它的构建模块有哪些?