写给自己看的面试题整理-算法&某东笔试题
-
排序(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
- js Array.prototype.sort 方法了解一下?
const swap(arr, a, b) { // a, b 是下标 let t = arr[a] arr[a] = arr[b] arr[b] = t } 复制代码
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] window.Array.prototype.sort.call(arr, function(a, b) { return a - b }) arr 复制代码
- 冒泡
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const bubleSort = function(arr) { for(let j = arr.length; j > 1; j--) { for(let i = 0; i < arr.length - 1; i++) { if (arr[i] > arr[i+1]) { let t = arr[i] arr[i] = arr[i+1] arr[i+1] = t } } } return arr } const x = bubleSort(arr) x 复制代码
- 选择
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const selectSort = function() { let index for(let i = 0; i < arr.length; i++) { index = i for(let j = i + 1; j < arr.length; j++) { if(arr[index] > arr[j]) { index = j } } if(index !== i) { let t = arr[i] arr[i] = arr[index] arr[index] = t } } return arr } const x = selectSort(arr) x 复制代码
- 计数
// 有一定的局限 只能用于整数 const counterSort = function() { } 复制代码
-
快速
const arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8] const quickSort(arr) { if(arr.length <= 1) { return arr } let midPos = Math.floor(arr.length / 2) // 调用了 js 原生 api 懒得写了 大体就是用 二分的思想吧--。 } 复制代码
-
插入
// 从后往前比较 知道碰到比当前项还要小的前一项时 将这一项插入到前一项的后面 复制代码
- 归并
-
二分查找法
-
翻转二叉树
第三个二叉树暂时先放弃了....
京东笔试题:
-
手写 Ajax 工具类,例如 request(url, option)
const request = function(url, option) { let xhr = new XMLHttpRequest() xhr.open(option, url) xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { // responseCallback() console.log(xhr.responseText) } } } 复制代码
-
跨域有哪些解决方案。 说说JSONP的实现。
function jsonp(setting) { settings.data = settings.data || {} settings.key = settings.key || 'callback' settings.callback = settings.callback || function() {} settings.data[settings.key] = '__onGetData__' window.__onGetData__ = function(data) { settings.callback(data) } let script = document.createElement('script') let query = [] for(let key in settings.data) { query.push(key + '=' + encodeURIComponent(settings.data[key])) } script.src = settings.url + '?' + query.join('&') document.head.appendChild(script) document.head.removeChild(script) } jsonp({ url: 'http://photo.sina.cn/aj/index', key: 'jsoncallback', data: { page: 1, cate: 'recommend', }, callback: function(ret) { console.log(ret) } }) 复制代码
-
CORS-跨域资源访问
-
-
js有哪些实现继承的方式。 闭包是什么?
- class extends
- 闭包
- 第一种说法 闭包可以用来间接访问一个变量,闭包可以用来隐藏一个变量
- 第二种说法: 闭包返回一个函数,这个函数可以操作其他函数内部的变量
function getAdder() { let n = 0 return function() { n++ console.log('n: ', n) } } let adder = getAdder() adder() adder() 复制代码
-
写一个函数把手机号格式化: 13499991212 => 134 9999 1212
-
写出一下代码的输出结果
let leng = 1 function fn() { console.log(this.leng) } let obj = { leng: 2, method1: function(fn) { fn() // undefined fn.call(this) // 2 arguments[0]() // undefined }, method2: function() { document.addEventListener('click', evt => this.method3(evt.type), false) }, method3: function(type) { console.log(type + ' : ' + this.leng ) // 'click: 2' }, } obj.method1(fn) obj.method2(fn) // 点击页面之后打印什么? 复制代码
-
写出下面代码的输出结果
let reg = /abc/g let str = 'abcd' reg.test(str) // true reg.test(str) // false 复制代码
-
写出一个复制对象的方法 包括浅复制 和 深复制
// 浅 let person = { age: 18, name: 'guakun', hobby: { first: 'code', second: 'code', } } let person2 = {} for(key in person) { person2[key] = person[key] } 复制代码
-
写出下面代码的输出结果
console.log(1) setTimeout(function() { console.log(2) }, 0) console.log(3) 复制代码
-
写出下面代码的输出结果
let p1 = {name: 'john', age: 30} let p2 = {name: 'lucy', age: 20} function modify1(obj) { p1 = {name: 'backus'} } function modify2(obj) { obj.name = 'guakun' } modify1(p1) modify2(p2) console.log(p1) // {name: 'backus'} console.log(p2) // {name: 'guakun', age: 20} 复制代码
-
如何实现以下效果
function add(num1) { return function(num2) { console.log(num1+num2) } } add(2)(5) 复制代码
-
解释一下变量提升(hoisting)
-
事件对象的 target 和 currentTarget 属性有什么区别
- event.target 返回的是触发事件的元素
- event.currentTarget 返回的是绑定事件的元素
-
DOM 事件流是什么,各浏览器的兼容性
捕获和冒泡 兼容性的问题我不会
-
load 和 DOM ready 有什么区别?
-
写一个找出数组中重复元素的函数, 例如[0, 1, 2, 3, 4, 1, 4] 返回[1, 4]
//计数排序 let a = [0, 1, 2, 3, 4, 1, 4] let hashTab = {} let repeateHashTab = {} for(let index = 0; index < a.length; index++) { if(!(a[index] in hashTab)){ hashTab[a[index]] = true } else { repeateHashTab[a[index]] = true } } console.log(Object.keys(repeateHashTab)) function getInt(arr) { let newArr = [] newArr = arr.map((item) => item-0) return newArr } console.log(getInt(Object.keys(hashTab))) 复制代码
-
如何提高滚动事件的性能
-
防抖
防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。
// 防抖动函数 function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate & !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; var myEfficientFn = debounce(function() { // 滚动中的真正的操作 }, 250); // 绑定监听 window.addEventListener('resize', myEfficientFn); 复制代码
-
节流
防抖函数确实不错,但是也存在问题,譬如图片的懒加载,我们希望在下滑过程中图片不断的被加载出来,而不是只有当停止下滑时候,图片才被加载出来。 这个时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。 节流函数:只允许一个函数在 X 毫秒内执行一次。 与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。 同样是利用定时器,看看简单的示例
// 简单的节流函数 function throttle(func, wait, mustRun) { var timeout, startTime = new Date(); return function() { var context = this, args = arguments, curTime = new Date(); clearTimeout(timeout); // 如果达到了规定的触发时间间隔,触发 handler if(curTime - startTime >= mustRun){ func.apply(context,args); startTime = curTime; // 没达到触发间隔,重新设定定时器 }else{ timeout = setTimeout(func, wait); } }; }; // 实际想绑定在 scroll 事件上的 handler function realFunc(){ console.log("Success"); } // 采用了节流函数 window.addEventListener('scroll',throttle(realFunc,500,1000)); 复制代码
-
-
谈下对 Promise 的理解
一种优雅的异步解决方案 // q function Promise() { return } let promise = new Promise(function(x, y) { setTimeout(()=>{ x(101) }, 3000) }) promise.then((z) => { console.log(z) }) // a function Promise(fn) { let status = 'pending' function successNotify() { status = 'resolved' toDoThen() } function failNotify() { status = 'rejected' toDoThen() } function toDoThen() { if(status === 'resolved') { for(let i=0; i< successArray.length; i++) { successArray[i].call() } } else if(status === 'rejected') { for(let i=0; i<failArray.length; i++) { failArray[i].call() } } } let successArray = [] let failArray = [] fn.call(undefined, successNotify, failNotify) return { then: function(successFn, failFn) { successArray.push(successFn) failArray.push(failFn) return undefined // 简化 } } } 复制代码
-
写出下面代码的输出结果(es6)
let x = 3 function fn (y = x) { let x = 4 console.log(y) } fn() // out: 3 复制代码