前端面试题总结

375 阅读5分钟

JS中的数据类型

  • JS中的数据类型由基本数据类型和复杂类型组成。

基本数据类型

JS中的基本数据类型有哪些?

  • NumberStringNullUndefinedBooleanSymbol
  • ES10新增了一种基本数据类型 BigInt

基本数据类型的检测方法是什么?

  • typeof 可以判断除null之外的基本数据类型属于哪一种具体的基本数据类型,typeof null 返回 Object
typeof 1  // "number"
typeof NaN // "number"

typeof '1' // "string"
typeof undefined // "undefined"
typeof true // "boolean"
typeof null // "object"
typeof Symbol() // "symbol"

typeof null 返回 object 的原因

不同的数据类型在底层都表示为二进制,在JavaScript中,二进制前三位都为0的话会被判断为Object类型,null的二进制表示全为0,所以执行typoeof null 会返回'object'。【你不知道的JS上 P103】

如何判断null

 var a = null
(!a && typeof a === 'object')//true

怎么理解基本数据类型是不可变的?

通过下图能很好的说明为什么基本类型是不可改变了,我们平时所做的操作其实都是对数据重新赋值。

复杂数据类型

复杂数据类型是 Object

typeof与复杂数据类型

  • typeof 函数 会返回function,其他复杂类型都会返回object
typeof function add (){} //"function"
typeof {} //"object"

复杂数据类型的检测方法:instanceof

  • obj1 instanceof obj2 如果 obj1 的原型链上有 ojb2.prototype,那么返回 true
[] instanceof Array //true
var obj = {}
obj instanceof Object

基本数据类型和复杂数据类型的区别

  1. 在内存中的存储方式
  • 基本数据类型存储在栈中,直接存储的是值。
  • 复杂数据类型,在栈中存储的是指向堆中的引用。
  1. 变量的复制
  • 复制基本数据类型,复制的是值的副本,复制之后两个值完全独立互不影响
   var a = 1;
   var b = a;
   a = 2;
   b // 1
  • 复制复杂数据类型,复制的是引用,复制之后的值也指堆中对应的值
   var obj = {
       a : 1
   }
   var obj2 = obj
   obj1.a = 2
   obj2.a // 2

函数参数是对象的情况

function test(person) {
  person.age = 26
  person = {
    name: 'luoyiluoyi',
    age: 30
  }

  return person
}
const p1 = {
  name: 'luoyi',
  age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?

var、let、const的区别

  1. var 是ES5的语法
  2. let,const是ES6的语法
  3. var 存在变量提升
  4. var 和 let 声明的是变量,可修改,const 声明的是常量,不可修改
  5. let const有块级作用域,var没有

let 和 const 定义的变量不会出现变量提升,而 var 定义的变量会提升。 let 和 const 是JS中的块级作用域 let 和 const 不允许重复声明(会抛出错误) let 和 const 定义的变量在定义语句之前,如果使用会抛出错误(形成了暂时性死区),而 var 不会。 const 声明一个只读的常量。一旦声明,常量的值就不能改变(如果声明是一个对象,那么不能改变的是对象的引用地址)

强制类型转换与隐式类型转换

强制类型转换

Number

  1. 数值
Number(1) //1

2.字符串

Number('1')//1
Number('luoyi') //NaN
  1. 布尔值
Number(true) //1
Number(false) //0
  1. undefined
Number(undefined) // NaN
  1. null
Number(null) // 0
  1. Object
  • valueOf()
  • toString()
let a = {a:1}
Number(a) //NaN
//过程
a.valueOf() //
a.toString() //
Number(a.toString())

String

  1. 数值
String(1) // '1'

2.字符串

String('luoyi') //'luoyi'

3.布尔值

String(false) // 'false'
String(true) // 'true'

4.undefined

String(undefined) //'undefined'

5.null

String(null) // 'null'

6.Object

let b = {b:1}
String(b)
//过程
b.toString() //如果是原始类型,那么执行String(b.toString())
b.valueOf() // 如果不是原始类型,valueOf(b.valueOf())。如果b.valueOf()返回的不是原始类型那么报错

Boolean

  1. Boolean(undefined),Boolean(null),Boolean(0),Boolean(+0),Boolean(-0),Boolean(NaN),Boolean('') 2.其余都为true

隐式类型转换

  1. 逻辑运算符
  2. ==
  3. 拼接字符串
[]+[] // ""
[]+{} //"[object Object]"
{}+[] // 0
{}+{} //"[object Object][object Object]"
true + true // 2
1+{a:1} // "1[object Object]"

0.1 + 0.2 !== 0.3

string 类型是不可变的,无论你在 string 类型上调用何种方法,都不会对值有改变。

for of 和 for in 的区别

相同点

  1. 循环都可以中断

不同的

  1. for of 遍历的是属性值,for in 遍历的是属性名
  2. for of 遍历有iterator接口的数据结构。

get请求和post请求有什么不同?

常见的前端攻击方式有哪些?

  1. XSS攻击

    XSS攻击的本质就是将攻击者恶意注入的代码执行。

  • 反射型攻击

    通过构造URL中的参数拼接恶意代码,页面中是直接读取的URL中的参数,这时候将恶意代码输入到页面中。

  • 存储型攻击

    通过构造URL中的参数拼接恶意代码,恶意代码被存储到数据库中,页面中从数据库读取数据,这时候将恶意代码输入到页面中。

  • 防范措施:

    1. 前端和后端在传递和接受数据都进行转码和解码。
    2. 在服务端设置HTTP头Content-Security-Policy: default-src 'self',或者在前端设置<meta http-equiv="Content-Security-Policy" content="form-action 'self';">
    3. HTTP-only Cookie: 在cookie中设置HttpOnly属性,那么通过js脚本将无法读取到cookie信息,攻击者完成 XSS 注入后也无法窃取此 Cookie。,这样能有效的防止 XSS 攻击。
    4. 提交表单的时候增加验证码,防止通过代码的方式提交表单。
  1. CRFS攻击

    攻击者利用登陆了某网站A的用户的登录信息,通过诱导用户点击网站B,在B网站上像A网站发送一些请求。

  • 解决方法:
  1. 根据HTTP请求头Referer判断请求的来源
  2. 用户每次像服务器提交的诗句都携带一个唯一的Token。

函数

  1. 函数可以拥有属性,函数的length属性是其声明的参数的个数