JS基础试题(一)

1、分别用迭代递归实现数组的扁平化 flatten

flatten([1, 2, [3, [4, [5]]]]) // [1, 2, 3, 4, 5]

解析:

// 迭代
const flatten = function (arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}
// 递归
const flatten = arr => arr.reduce((a, b) => 
  (Array.isArray(b) ? [...a, ...flatten(b)] : [...a, b]), [])

拓展

2、改造下列函数,使之输出0-9

for (var i = 0; i< 10; i++){
   setTimeout(() => {
     console.log(i)
   }, 1000)
}

解析:
setTimeout定义的操作在函数调用栈清空之后才会执行 https://www.jianshu.com/p/9b4a54a98660

setTimeout(function () {
    console.log('aaaa')
}, 0)
console.log('bbbb')

方法

// 方法一
for (let i = 0; i< 10; i++){
  setTimeout(() => {
    console.log(i)
  }, 1000)
}
// 方法二
for (var i = 0; i< 10; i++){
  ((i) => {
    setTimeout(() => {
      console.log(i)
    }, 1000)
 })(i)
}
// 方法三
for (var i = 0; i< 10; i++){
 // 此时的setTimeout 无效
  setTimeout((() => {
    console.log(i)
  })(), 1000)
}

3、作用域和闭包

var name = 'The Window'
var object = {
  name : 'My Object',
  getNameFunc: function(){
   var that = this
   console.log(this.name)
   return function(){
    console.log(this.name)
    console.log(that.name)
   }
  }
}
object.getNameFunc()()

解析:

闭包有以下三个特性

  • 可以访问当前函数以外的变量
  • 即使外部函数已经返回,闭包仍能访问外部函数定义的变量
  • 闭包可以更新外部变量的值
// My Object
// The Window
// My Object

4、作用域和闭包

var n = 123
let m = 789
function fn () {
  var n = 99
  console.log(n, m)
  console.log(window.n, window.m)
  add = function () { n = 100 }
  return () => console.log(n)
}
var result = fn()
result() 
add()
result()
var demo = fn()
demo()

解析:

99 789
123 undefined
99
100
99 789
123 undefined
99

5、http请求的get和post区别

  • get是从服务器上取数据,post是向服务器传数据
  • get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制
  • get安全性非常低,post安全性较高
    image

拓展

  • TCP的三次握手
  • http协议的方法
  • https通信机制

6、Object.assign 模拟实现

function assign (target) {
      if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
      }
      var to = Object(target)
      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index]
        if (nextSource != null) {
          for (var nextKey in nextSource) {
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey]
            }
          }
        }
      }
      return to
    }

拓展

7、 模拟实现一个call

  • 不传入第一个参数,那么默认为window
  • 改变了this指向,让新的对象可以执行该函数。思路是否可以变成给新的对象添加一个函数,然后在执行完以后删除
Function.prototype.myCall = function (context) {
  var context = context || window
  // 给context添加一个属性
  // getValue.call(a, 'cdt', '40') => a.fn = getValue
  context.fn = this
  // 将context后面的参数取出来
  var args = [...arguments].slice(1)
  // getValue.call(a, 'cdt', '40') => a.fn('cdt', '40')
  var result = context.fn(...args)
  // 删除fn
  delete context.fn
  return result
}

// 执行代码
var val = {
value: 1
}
function getValue(name, age) {
  console.log(name)
  console.log(age)
  console.log(this.value)
}
getValue.myCall(val, 'cdt', '40') // -> cdt 40 1

拓展

  • call 和apply

  • call在严格模式下第一个参数可以为null,无作用域

  • 伪数组转数组

    // 第一种方法
    Array.prototype.slice.call(arrayLike)
    
    // 第二种方法
    [...arrayLike]
    
    // 第三种方法
    Array.from(arrayLike)
    

8、下面代码中 a 在什么情况下会打印 1?

var a = ?
if(a == 1 && a == 2 && a == 3){
 console.log(1)
}

答案:

var a = {
  i: 1,
  toString () {
    return a.i++
  }
}

解析:

引用类型在比较运算符时候,隐式转换会调用本类型toStringvalueOf方法。

执行 a == 1时,会调用a这个对象默认值1,并且执行完之后会执行i++,那么a就等于2,以此类推。但是这个判断语句必须按照顺序判断。

拓展

9、给定两个数组,写一个方法来计算它们的交集

var nums1 = [1, 2, 2, 1], nums2 = [2, 2, 3, 4]
// 1. [NaN].indexOf(NaN) === -1,这样子的话 NaN会检测不到
var arr = nums1.filter(item => {
  return nums2.indexOf(item) > -1
})

// 2.  这个方法可以
var newArr2 = nums1.filter((item) => {
  return nums2.includes(item)
})

10、密码安全

密码安全虽然大多是后端的事情,但是作为一名优秀的前端程序员也需要熟悉这方面的知识。

加盐:
对于密码存储来说,必然是不能明文存储在数据库中的,否则一旦数据库泄露,会对用户造成很大的损失。并且不建议只对密码单纯通过加密算法加密,因为存在彩虹表的关系(彩虹表:理解为用于加密散列逆运算的预先计算好的表)

通过需要对密码加盐,然后进行几次不同加密算法的加密。
// 加盐也就是给原密码添加字符串,增加原密码长度
sha256(sha1(md5(salt + password + salt)))

但是加盐并不能阻止别人盗取账号,只能确保即使数据库泄露,也不会暴露用户的真实密码。一旦攻击者得到了用户的账号,可以通过暴力破解的方式破解密码。对于这种情况,通常使用验证码增加延时或者限制尝试次数的方式。并且一旦用户输入了错误的密码,也不能直接提示用户输错密码,而应该提示账号或密码错误。


 上一篇
阿里前端监控 阿里前端监控
为什么要有前端监控 随着前端项目的迭代更新,页面的代码逐渐增多,逻辑也越来越复杂,这时可能会遇到以下问题 如果用户访问我们的站点时遇到错误,我们无法在第一时间得知,还需要用户上报才能发现,而且上报也只能得到出现了错误,无法得知具体的
2018年10月12日
下一篇 
ueditor多图上传至阿里云oss ueditor多图上传至阿里云oss
今天做百度编辑器UEditor多图上传至阿里云oss,打开的弹框中有三个功能:插入图片、本地上传和图片搜索,其中插入图片功能正常,剩余两个需要自行完善 本地上传 本地图片上传有两个坑,分别是获取token,以及成功上传后的显示 由于我
2018年10月11日