面试问答录

CSS

  • 讲一下float

  • 透明度设置

  • 如何画一个三角形

  • CSS盒模型

  • CSS布局

  • 元素垂直居中的方法 / 元素水平居中、垂直居中方法(怎么让一个 div 水平垂直居中)

  • CSS预处理器

  • grid、Flex布局及属性,flex布局设置居中

  • CSS性能优化

  • 响应式布局

  • CSS动画,自定义动画

  • CSS单位

  • CSS伪元素

JavaScript

  • DOM是什么?关于DOM的api有哪些?

  • 几个很实用的BOM属性对象方法

  • 闭包

  • JS基本数据类型,null和undefined区别

  • JS原型链,原型链顶端是什么?Object原型?它原型的原型?

  • DOM增删改查(手写),元素前面插入

  • 讲一下同步、异步

  • 了解的JS标准

  • sort函数

  • ES6的新特性有用过哪些?

Vue

  • 简单讲一下vue

  • vue生命周期,vue生命周期中获取路由参数

  • vue指令

  • Vue原理性相关问题:双向数据绑定原理、讲一下MVVM及原理

网络

  • linux知道的基本操作

  • 服务器Tomcat与Nginx

  • 如何搭建一个网站

Web

  • web性能优化

项目相关

  • 你遇到过的最有挑战的项目?介绍一下这个项目和你曾经做过项目的主要功能。(注意打磨个人项目)

HTTP/浏览器

  • cookie、session及区别

  • 跨域有接触过吗?讲一讲跨域。

前端工程化等或其它

  • npm有了解吗,底层原理是怎样的?

  • webpack用过吗?(前端工程化)

  • 测试相关、前端自动化测试有了解过吗?

  • 有了解过什么新的技术吗?不一定是前端专业领域

笔试知识点提炼

JavaScript中=区别

  • 相等运算符 ==

  • 严格相等运算符 ===

==比较

===比较

1)两个值类型相同,再进行三个等号(===)比较

2)类型不同,先类型转换,再===比较

a. 原始类型的值 => 转数值类型比较

b. 对象与原始类型值比较 => 对象转原始类型值比较

c.undefinednull => 比较其他类型 false,互比 true

d. 不相等运算符 != => 返回相反值

1)不同类型值 => false

2)同一原始类型值 => 比较值 如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN()来判断)

3)复合类型值 => 比较指向同一地址

4)undefinednull => true

5) 严格不相等运算符!== => 先求严格相等运算符的结果,然后返回相反值

=== 严格相等运算符

  • 1)不同类型值 => false

     1 === "1" // false
     true === "true" // false
  • 2)同一原始类型值 => 比较值

    • 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。

   1 === 0x1 // true 十进制与十六进制的1比较
   NaN === NaN  // false
   +0 === -0 // true

NaN与任何值都不相等(包括自身);正0等于负0

  • 3)复合类型值 => 比较指向同一地址

    • 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址。

     {} === {} // false 两个空对象
     [] === [] // false 两个空数组
     (function () {} === function () {}) // false 两个空函数
     // 运算符两边的空对象、空数组、空函数的值,都存放在不同的内存地址,所以结果是false
     /* 如果两个变量引用同一个对象,则它们相等 */
     var v1 = {};
     var v2 = v1;
     v1 === v2 // true
     /* 两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值 */
     new Date() > new Date() // false
     new Date() < new Date() // false
     new Date() === new Date() // false
  • 4)undefinednull => true undefined和null与自身严格相等

  • 5)严格不相等运算符 !== => 先求严格相等运算符的结果,然后返回相反值

     1 !== '1' // true

==相等运算符

  • 1)原始类型的值 => 转数值类型比较

    • 原始类型的数据会转换成数值类型再进行比较。

 1 == true // true  等同于 1 === Number(true) => 1===1
 ​
 0 == false // true 等同于 0 === Number(false)
 ​
 2 == true // false 等同于 2 === Number(true)
 ​
 'true' == true // false
 // 等同于 Number('true') === Number(true) => 等同于 NaN === 1
 ​
 '' == 0 // true
 // 等同于 Number('') === 0 => 等同于 0 === 0
 ​
 '' == false  // true
 // 等同于 Number('') === Number(false) => 等同于 0 === 0
 ​
 '1' == true  // true
 // 等同于 Number('1') === Number(true) => 等同于 1 === 1
 ​
 '\n  123  \t' == 123 // true 因为字符串转为数字时,省略前置和后置的空格
  • 2)对象与原始类型值比较 => 对象转原始类型值比较

    • 对象(这里指广义的对象,包括数组和函数)。

 [1] == 1 // true  等同于 Number([1]) == 1
 ​
 [1] == '1' // true 等同于 Number([1]) == Number('1')
 ​
 [1] == true // true 等同于 Number([1]) == Number(true)
  • 3)undefined null => 比较其他类型false,互比true。

false == null // false
false == undefined // false

0 == null // false
0 == undefined // false

undefined == null // true

  • 绝大多数情况下,对象与undefined和null比较,都返回false。只有在对象转为原始值得到undefined时,才会返回true。

  • 4)不相等运算符 != => 返回相反值。

聊聊JavaScript中的Object.defineProperty()

在Vue2.x中,实现响应式的原理Object.defineProperty()这个ES5的API是核心。

Object.defineProperty()

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。 => Object.defineProperty() 通过定义属性的元数据信息精准控制属性的行为。

传统定义JS对象的方法:

let obj = {};
let obj = new Object; 
let obj = Object.create();

通常我们使用到的Object对象,在给对象设置属性时,一般通过对象的. 操作符或者 [] 操作符直接赋值,或直接使用队形字面量方式赋值,比如 obj.a = 10 。此类赋值后属性值可以后续更改,且对象可以被for..in 或 Object.keys 枚举遍历,即通过循环方式获取到该对象的属性值。

当只想定义了对象后,后续无法更改属性值或无法枚举时(精确的添加或修改对象的属性),我们就用到了 Object.defineProperty()。

语法

Object.defineProperty(obj, prop, descriptor)

参数说明如下:

  • obj:Object,要定义属性的对象。

  • prop: String||Symbol,要定义或修改的属性的名称或 Symbol

  • descriptor: Object,要定义或修改的属性描述符

返回值:Object,被传递给函数的对象。

默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的

接下来我们来着重看一下 descriptor 属性描述对象:

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符。一个描述符只能是这两者其中之一;不能同时是两者。

  • 数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。

  • 存取描述符是由 getter 函数和 setter 函数所描述的属性。

两种描述符都是对象,该描述对象共有 configurableenumerablevaluewritablegetset 等6个可选键值。

描述

默认值

configurable

configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除

false

enumerable

enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中

false

writable

writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变

false

value

该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)

undefined

get

没有 getter,则为 undefined。当访问该属性时,会调用此函数。

执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的 this 并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值

undefined

set

没有 setter,则为 undefined。当属性值被修改时,会调用此函数。

该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象

undefined

描述符可拥有的键值

configurable

enumerable

writable

value

get

set

数据描述符

×

×

存取描述符

×

×

如果一个描述符不具有 valuewritableget set 中的任意一个键,那么它将被认为是一个数据描述符。

如果一个描述符同时拥有 value writable get set 键,则会产生一个异常。

Object.defineProperty()小练:

var o = {};
Object.defineProperty(o, "a",{
    value: 1,
    writable: false
});
console.log(o.a);  
o.a = 2;  
console.log(o.a);  
// 两次输出结果?

第一次输出结果:1 第二次输出结果:1,当o.a=2时抛出异常,writable为false,value值不可被更改

=> 不用const,此方法可以使定义的变量不可变。

/* 来源:2020奇安信前端秋招 */
var o = { a: 1 };
Object.defineProperty(o, "b", {value: 2, writable: false, enumerable: false, configurable: true});
o.a = 2;
o.b = 3;
console.log(o.a, o.b)
// 代码输出的结果?

输出结果:2 2

JavaScript Array map()方法

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 不会对空数组进行检测;不会改变原始数组

语法

array.map(function(currentValue,index,arr), thisValue)

参数说明:

参数

Required

描述

function(currentValue, index,arr)

必须√

函数,数组中的每个元素都会执行这个函数 函数参数如下: currentValue(必须√):当前元素的值 index:当前元素的索引值 arr:当前元素属于的数组对象

thisValue

可选

对象作为该执行回调时使用,传递给函数,用作 "this" 的值。 如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。

/* 来源:2020奇安信前端秋招 */
console.log([1,undefined,3,5].map((_,n)=>n))
// 上述代码在控制台的运行结果是什么?

输出结果:[0,1,2,3]

/* 来源:2020小鱼易连前端秋招 */
console.log([1,2,3].map(parseInt));
// 上述代码在控制台的输出结果是什么?

输出结果:[1,NaN,NaN]

parseInt 语法如下:

parseInt(string, radix)
// string 必需。要被解析的字符串。
// radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
/** 如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开 头,将以 16 为基数。
如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
**/
parseInt('1', 0) -> 1   radix 为 0,且string参数不以“0x”和“0”开头时,parseInt() 会根据十进制来解析,所以结果为 1;
parseInt('2', 1) -> NaN radix 为 1,在基数为1(1进制)表示的数中,最大值小于2,超出区间范围,无法解析,所以结果为 NaN;
parseInt('3', 2) -> NaN 同理,radix 为 2,基数为2(2进制)表示的数中,最大值小于3,所以结果为 NaN。
=> 因为parseInt接收两个参数,所以结果为 [1, NaN, NaN]

ES6 Symbol类型

Symbol:ES6引入的一种新的原始数据类型,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一。

Symbol 值通过 Symbol() 函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol() 函数前不能使用 new 命令,否则会报错。

因为生成的 Symbol 是一个原始类型的值,不是对象,所以不能使用 new 命令来调用。另外,由于 Symbol 值不是对象,所以也不能添加属性。基本上,它是一种类似于字符串的数据类型。

  • Symbol() 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述。

  • Symbol() 函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol 函数的返回值是不相等的。

  • Symbol 值不能与其他类型的值进行运算,会报错。

  • Symbol 值可以显式转为字符串,也可以转为布尔值,但是不能转为数值。

let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
// -------------------------------
let sym = Symbol();
Boolean(sym) // true
!sym  // false
if (sym) {
  // ...
}
Number(sym) // TypeError
sym + 2 // TypeError

Symbol小练:

以下关于ES6中Symbol的描述正确的是()

A.Symbol是一种JS原始数据类型

B.Symbol("a")===Symbol("a")的结果为true

C.Symbol.for("a")===Symbol.for("a")的结果为true

D.Symbol().instanceof Object结果为true

A C

D: Symbol为原始数据类型,即类型是Symbol D为false。

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。


Object.assign

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

简单来说,就是Object.assign()是对象的静态方法,可以用来复制对象的可枚举属性到目标对象,利用这个特性可以实现对象属性的合并。

语法

Object.assign(target, ...sources)
// 参数: target--->目标对象 source--->源对象
// 返回值:target,即目标对象

如果目标对象与源对象具有相同的 key,则目标对象中的属性将被源对象中的属性覆盖,后面的源对象的属性将类似地覆盖前面的源对象的属性。

  • 原型链上的属性和不可枚举属性不能被复制。

JS delete操作符

  • delete操作符不会影响数组长度。

var z=1;y=z=typeof y;console.log(y)  // undefined
// js中赋值操作结合律是右至左的 ,即从最右边开始计算值赋值给左边的变量。等价于下面的代码
var z = 1
z = typeof y;
var y = z;
console.log(y);

JavaScript_经典面试题