一些js编程题

数组扁平化

例:
输入:[[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10]
输出:[ 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10 ]

方法一

var newArr = []
function flatten(arr) {
  for (var i = 0; i < arr.length; i++) {
    if (Object.prototype.toString.call(arr[i]) === '[object Array]') {
      flatten(arr[i])
    } else {
      newArr.push(arr[i])
    }
  }
}

方法二

var flatten = function(array) {
  return array.reduce(function(previous, val) {
    if (Object.prototype.toString.call(val) !== '[object Array]') {
      return previous.push(val), previous
    }
    return Array.prototype.push.apply(previous, flatten(val)), previous
  }, [])
}

方法三

function flatten(arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}

实现 map

Array.prototype.myMap = function(callback) {
  var arr = []
  for (var i = 0; i < this.length; i++) {
    var item = callback(this[i], i)
    arr.push(item)
  }
  return arr
}

实现 bind

Function.prototype.myBind = function(context) {
  var self = this
  var args = [].slice.call(arguments, 1)
  return function() {
    return self.apply(context, args.concat(arguments))
  }
}

实现一个简单的字符串模版引擎

效果如下:

var str = 'hello, i am <%=user%>, from <%=location%>'
var compiled = template(str)
compiled({ user: 'zzw', location: 'ez' }) // 'hello, i am zzw, from ez'

代码:

function template(temp) {
  var temp = temp
  return function(obj) {
    var reg = /<%=(\w+)%>/
    var result
    console.log(temp)
    while ((result = reg.exec(temp))) {
      var key = result[1]
      var value = obj[key]
      temp = temp.replace(result[0], value)
    }
    return temp
  }
}

实现深克隆

function deepClone(obj) {
  var result,
    oClass = isClass(obj)
  //确定result的类型
  if (oClass === 'Object') {
    result = {}
  } else if (oClass === 'Array') {
    result = []
  } else {
    return obj
  }
  for (key in obj) {
    var copy = obj[key]
    if (isClass(copy) == 'Object' || isClass(copy) == 'Array') {
      result[key] = arguments.callee(copy) //递归调用
    } else {
      //如果为基本数据类型
      result[key] = obj[key]
    }
  }
  return result
}
//返回传递给他的任意对象的类
function isClass(o) {
  if (o === null) return 'Null'
  if (o === undefined) return 'Undefined'
  return Object.prototype.toString.call(o).slice(8, -1)
}

深克隆变形题目:将 json 字符串所有键名第一个首字母转为大写(考虑嵌套对象)

例:输入

{"hyKey":"myValue","q23":"123","arr":[1,2,3],"obj":{"name":"zzw"},"null":null}

输出:

{"HyKey":"myValue","Q23":"123","Arr":[1,2,3],"Obj":{"Name":"zzw"},"Null":null}
function toUpperCase1(obj) {
  var result,
    oClass = isClass(obj)
  if (oClass === 'Object') {
    result = {}
  } else if (oClass === 'Array') {
    result = []
  } else {
    return obj
  }
  for (var key in obj) {
    var copy = obj[key]
    if (isClass(copy) == 'Object' || isClass(copy) == 'Array') {
      result[key.slice(0, 1).toUpperCase() + key.slice(1)] = arguments.callee(
        copy
      )
    } else {
      result[key.slice(0, 1).toUpperCase() + key.slice(1)] = obj[key]
    }
  }
  return result
}

事件委托

实现:给定一个 ul 列表,里面有若干个 li 标签,li 里面也嵌套了若干标签,要求点击标签,弹出当前 li 在 ul 中的位置.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <ul id="ul">
        <li><a href="#"><span>li-a-span</span></a></li>
        <a href="#">a</a>
        <li><a href="#"><span>li-a-span</span></a></li>
        <li><a href="#"><span>li-a-span</span></a></li>
        <li><a href="#"><span>li-a-span</span></a></li>
        <li><a href="#"><span>li-a-span</span></a></li>
    </ul>
</html>
var ul = document.getElementById('ul')
ul.addEventListener('click', function(e) {
  // 事件委托
  var e = e.target
  while (e.nodeName != 'LI') {
    e = e.parentNode
  }
  var childrenArr = [].slice.apply(ul.children)
  var liArr = childrenArr.filter(function(child) {
    if (child.nodeName == 'LI') {
      return child
    }
  })
  console.log(liArr.indexOf(e))
})

输出字符串中所有的叠词

输入: '晴川历历汉阳树,芳草萋萋鹦鹉洲'
输出: [ '历历', '萋萋' ]

function rw(str) {
  var result = []
  for (var i = 1; i < str.length; i++) {
    if (str[i] == str[i - 1]) {
      result.push(str.slice(i - 1, i + 1))
    }
  }
  return result
}

实现一个 add 函数

执行如下:
add(1, 2); // 3
add(1)(2); // 3
add(1, 2, 3)(1, 4)(2, 2)(1) // 16

function add() {
  var sum = 0
  var arr = [].slice.call(arguments)
  for (var i = 0; i < arr.length; i++) {
    sum += arr[i]
  }
  var temp = function() {
    var arr = [].slice.call(arguments)
    for (var i = 0; i < arr.length; i++) {
      sum += arr[i]
    }
    return temp
  }

  temp.toString = function() {
    return sum
  }
  return temp
}

一个考察了 this/变量提升/构造函数返回值/运算符优先级的题目

function Foo() {
  getName = function() {
    alert(1)
  } // 没有var
  return this
}
Foo.getName = function() {
  alert(2)
}
Foo.prototype.getName = function() {
  alert(3)
}
var getName = function() {
  alert(4)
}
function getName() {
  alert(5)
}

/* 写出输出 */
Foo.getName() // 2
getName() // 4 => 变量提升
Foo().getName() // 1 => 函数调用this指向 window.getName()
getName() // 1
new Foo.getName() // 2 => new (Foo.getName)() 运算符优先级
new Foo().getName() // 3 => (new Foo()).getName() 构造函数返回值
new new Foo().getName() // 3 => new Foo().getName()

实现一个 LazyMan

// 实现一个LazyMan,可以按照以下方式调用:
LazyMan(“Hank”)
// 输出: Hi! This is Hank!

LazyMan(“Hank”).sleep(10).eat(“dinner”)
// 输出:
// Hi! This is Hank!
// 等待10秒..
// Wake up after 10
// Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)
// 输出:
// Hi This is Hank!
// Eat dinner~
// Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”)
// 输出:
// 等待5秒
// Wake up after 5
// Hi This is Hank!
// Eat supper
以此类推。

答案

function _LazyMan(name) {
  const self = this
  this.taskqueue = []
  console.log(`Hi, This is ${name}`)
  setTimeout(() => {
    self.next()
  }, 0)
}

_LazyMan.prototype.next = function() {
  const fn = this.taskqueue.shift()
  fn && fn()
}

_LazyMan.prototype.sleep = function(time) {
  const self = this
  const fn = function() {
    setTimeout(() => {
      console.log(`Wake up after ${time}`)
      self.next()
    }, time * 1000)
  }
  this.taskqueue.push(fn)
  return this
}

_LazyMan.prototype.eat = function(name) {
  const self = this
  const fn = function() {
    console.log(`Eat ${name}`)
    self.next()
  }
  this.taskqueue.push(fn)
  return this
}

_LazyMan.prototype.sleepFirst = function(time) {
  const self = this
  const fn = function() {
    setTimeout(() => {
      console.log(`Wake up after ${time}`)
      self.next()
    }, time * 1000)
  }
  this.taskqueue.unshift(fn)
  return this
}

function LazyMan(name) {
  return new _LazyMan(name)
}

实现一个 compose 方法,要求如下

function fun1(ctx, next) {
  ctx.count++
  console.log(ctx.count)
  next()
}
function fun2(ctx, next) {
  ctx.count++
  console.log(ctx.count)
  setTimeout(function() {
    next()
  }, 1000)
}
function fun3(ctx, next) {
  ctx.count++
  console.log(ctx.count)
  next()
}
compose([fun1, fun2, fun3])({ count: 1 }) // 2 3 4

答案

function compose(arr) {
  return function(ctx) {
    const next = function() {
      const fn = arr.shift()
      fn && fn(ctx, next)
    }
    next()
  }
}

实现一个 composite 方法,要求如下

function add(a, b) {
  return a + b
}
function square(a) {
  return a * a
}
function plusOne(c) {
  return c + 1
}

var addSquareAndPlusOne = composite(add, square, plusOne)

console.log(addSquareAndPlusOne(1, 2)) // 10

答案:

function composite(...fns) {
  return function(...args) {
    return fns.reduce((accu, curr) => {
      return typeof accu === 'function' ? curr(accu(...args)) : curr(accu)
    })
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,657评论 18 139
  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,772评论 0 8
  • 母亲(一百) 文||与你相识 以朝圣的目光期待 那个熟悉的天地里 有您永不停息的身影 爱,是今生今世的永恒 牵过的...
    与你相识_40fa阅读 259评论 2 4
  • 我是从某微信公众号的作者简介上知道简书的,简书签约作者,貌似很酷的样子。 而后,我如同其他不懂的知识一般,求助了度...
    独明阅读 253评论 0 1
  • 文/苏悸婉 一段残缺的婚姻固然已经不幸了,可是在这段不幸婚姻当中的人却要以孩子的名义进行道德绑架,以爱的名义去慈悲...
    苏悸婉阅读 1,058评论 6 9