1. babel和polyfill
Babel
: Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码。注意:Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 APIPolyfill
: Polyfill的准确意思为,用于实现浏览器并不支持的原生API的代码。
2. jpg, jpeg和png区别
- jpg是jpeg的缩写, 二者一致
- PNG就是为取代GIF而生的, 无损压缩, 占用内存多
- jpg牺牲图片质量, 有损, 占用内存小
- PNG格式可编辑。如图片中有字体等,可利用PS再做更改。JPG格式不可编辑
3. git rebase和merge区别
前端性能优化
- 减少HTTP请求(合并css、js,雪碧图/base64图片)
- 压缩(css、js、图片皆可压缩,使用webpack uglify和 svg)
- 样式表放头部,脚本放底部
- 使用CDN(这部分,不少前端都不用考虑,负责发布的兄弟可能会负责搞好)
- http缓存
- bosify图片压缩: 根据具体情况修改图片后缀或格式 后端根据格式来判断存储原图还是缩略图
- 懒加载, 预加载
- 替代方案: 骨架屏, SSR
- webpack优化
原生通信
1.JSBridge通信原理, 有哪几种实现的方式?
JsBridge给JavaScript提供了调用Native功能,Native也能够操控JavaScript。这样前端部分就可以方便使用地理位置、摄像头以及登录支付等Native能力啦。JSBridge构建 Native和非Native间消息通信的通道,而且是 双向通信的通道。
- JS 向 Native 发送消息 : 调用相关功能、通知 Native 当前 JS 的相关状态等。
- Native 向 JS 发送消息 : 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等。
2.实现一个简单的 JSBridge,设计思路?
算法相关
1. 二分查找和冒泡排序
- 二分查找: 递归(分左右, 传递start,end参数)和非递归(使用while(l < h))
- 冒泡排序: 两个for循环
2. 快速排序
function quickSort (arr) { if (arr.length < 2) return arr var middle = Math.floor(arr.length / 2) var flag = arr.splice(middle, 1)[0] var left = [], right = [] for (var i = 0; i < arr.length; i++) { if (arr[i] < flag) { left.push(arr[i]) } else { right.push(arr[i]) } } return quickSort(left).concat([flag], quickSort(right)) }
3. 最长公共子串
function findSubStr(str1, str2) { if (str1.length > str2.length) { [str1, str2] = [str2, str1] } var result = '' var len = str1.length for (var j = len; j > 0; j--) { for (var i = 0; i < len - j; i++) { result = str1.substr(i, j) if (str2.includes(result)) return result } } } console.log(findSubStr('aabbcc11', 'ppooiiuubcc123'))
4. 最长公共子序列(LCS动态规划)
// dp[i][j] 计算去最大长度,记住口诀:相等左上角加一,不等取上或左最大值 function LCS(str1, str2){ var rows = str1.split("") rows.unshift("") var cols = str2.split("") cols.unshift("") var m = rows.length var n = cols.length var dp = [] for(var i = 0; i < m; i++){ dp[i] = [] for(var j = 0; j < n; j++){ if(i === 0 || j === 0){ dp[i][j] = 0 continue } if(rows[i] === cols[j]){ dp[i][j] = dp[i-1][j-1] + 1 //对角+1 }else{ dp[i][j] = Math.max( dp[i-1][j], dp[i][j-1]) //对左边,上边取最大 } } console.log(dp[i].join(""))//调试 } return dp[i-1][j-1] } //!!!如果它来自左上角加一,则是子序列,否则向左或上回退。 //findValue过程,其实就是和 就是把T[i][j]的计算反过来。 // 求最长子序列 function findValue(input1,input2,n1,n2,T){ var i = n1-1,j=n2-1; var result = [];//结果保存在数组中 console.log(i); console.log(j); while(i>0 && j>0){ if(input1[i] == input2[j]){ result.unshift(input1[i]); i--; j--; }else{ //向左或向上回退 if(T[i-1][j]>T[i][j-1]){ //向上回退 i--; }else{ //向左回退 j--; } } } console.log(result); }
5. 数组去重,多种方法
- 双for循环, splice剔除并i--回退
- indexOf等于index
- filter indexOf === index
- 新数组indexOf === index
- 使用空对象等
6. 实现一个函数功能:sum(1,2,3,4..n)转化为 sum(1)(2)(3)(4)…(n)
// 使用柯里化 + 递归 function curry ( fn ) { var c = (...arg) => (fn.length === arg.length) ? fn (...arg) : (...arg1) => c(...arg, ...arg1) return c }
7. 反转二叉树
var invertTree = function (root) { if (root !== null) { [root.left, root.right] = [root.right, root.left] invertTree(root.left) invertTree(root.right) } return root }
8. 贪心算法解决背包问题
var items = ['A','B','C','D'] var values = [50,220,60,60] var weights = [5,20,10,12] var capacity = 32 //背包容积 greedy(values, weights, capacity) // 320 function greedy(values, weights, capacity) { var result = 0 var rest = capacity var sortArray = [] var num = 0 values.forEach((v, i) => { sortArray.push({ value: v, weight: weights[i], ratio: v / weights[i] }) }) sortArray.sort((a, b) => b.ratio - a.ratio) sortArray.forEach((v, i) => { num = parseInt(rest / v.weight) rest -= num * v.weight result += num * v.value }) return result }
9. 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
function FindNumbersWithSum(array, sum) { var index = 0 for (var i = 0; i < array.length - 1 && array[i] < sum / 2; i++) { for (var j = i + 1; j < array.length; j++) { if (array[i] + array[j] === sum) return [array[i], array[j]] } //index = array.indexOf(sum - array[i], i + 1) // if (index !== -1) { // return [array[i], array[index]] //} } return []
10. 二叉树各种(层序)遍历
// 根据前序和中序重建二叉树 /* function TreeNode(x) { this.val = x; this.left = null; this.right = null; } */ function reConstructBinaryTree(pre, vin) { var result = null if (pre.length === 1) { result = { val: pre[0], left: null, right: null } } else if (pre.length > 1) { var root = pre[0] var vinRootIndex = vin.indexOf(root) var vinLeft = vin.slice(0, vinRootIndex) var vinRight = vin.slice(vinRootIndex + 1, vin.length) pre.shift() var preLeft = pre.slice(0, vinLeft.length) var preRight = pre.slice(vinLeft.length, pre.length) result = { val: root, left: reConstructBinaryTree(preLeft, vinLeft), right: reConstructBinaryTree(preRight, vinRight) } } return result } // 递归 // 前序遍历 function prevTraverse (node) { if (node === null) return; console.log(node.data); prevTraverse(node.left); prevTraverse(node.right); } // 中序遍历 function middleTraverse (node) { if (node === null) return; middleTraverse(node.left); console.log(node.data); middleTraverse(node.right); } // 后序遍历 function lastTraverse (node) { if (node === null) return; lastTraverse(node.left); lastTraverse(node.right); console.log(node.data); } // 非递归 // 前序遍历 function preTraverse(tree) { var arr = [], node = null arr.unshift(tree) while (arr.length) { node = arr.shift() console.log(node.root) if (node.right) arr.unshift(node.right) if (node.left) arr.unshift(node.left) } } // 中序遍历 function middleTraverseUnRecursion (root) { let arr = [], node = root; while (arr.length !== 0 || node !== null) { if (node === null) { node = arr.shift(); console.log(node.data); node = node.right; } else { arr.unshift(node); node = node.left; } } } // 广度优先-层序遍历 // 递归 var result = [] var stack = [tree] var count = 0 var bfs = function () { var node = stack[count] if (node) { result.push(node.value) if (node.left) stack.push(node.left) if (node.right) stack.push(node.right) count++ bfs() } } bfs() console.log(result) // 非递归 function bfs (node) { var result = [] var queue = [] queue.push(node) while (queue.length) { node = queue.shift() result.push(node.value) node.left && queue.push(node.left) node.right && queue.push(node.right) } return result }
11. 各种排序
// 插入排序 function insertSort(arr) { var temp for (var i = 1; i < arr.length; i++) { temp = arr[i] for (var j = i; j > 0 && temp < arr[j - 1]; j--) { arr[j] = arr[j - 1] } arr[j] = temp } return arr } console.log(insertSort([3, 1, 8, 2, 5])) // 归并排序 function mergeSort(array) { var result = array.slice(0) function sort(array) { var length = array.length var mid = Math.floor(length * 0.5) var left = array.slice(0, mid) var right = array.slice(mid, length) if (length === 1) return array return merge(sort(left), sort(right)) } function merge(left, right) { var result = [] while (left.length || right.length) { if (left.length && right.length) { if (left[0] < right[0]) { result.push(left.shift()) } else { result.push(right.shift()) } } else if (left.length) { result.push(left.shift()) } else { result.push(right.shift()) } } return result } return sort(result) } console.log(mergeSort([5, 2, 8, 3, 6])) // 二分插入排序 function twoSort(array) { var len = array.length, i, j, tmp, low, high, mid, result result = array.slice(0) for (i = 1; i < len; i++) { tmp = result[i] low = 0 high = i - 1 while (low <= high) { mid = parseInt((high + low) / 2, 10) if (tmp < result[mid]) { high = mid - 1 } else { low = mid + 1 } } for (j = i - 1; j >= high + 1; j--) { result[j + 1] = result[j] } result[j + 1] = tmp } return result } console.log(twoSort([4, 1, 7, 2, 5]))
12. 使用尾递归对斐波那契优化
递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
// 传统递归斐波那契, 会造成超时或溢出 function Fibonacci (n) { if ( n <= 1 ) {return 1}; return Fibonacci(n - 1) + Fibonacci(n - 2); } Fibonacci(10) // 89 Fibonacci(100) // 超时 Fibonacci(500) // 超时 // 使用尾递归优化, 可规避风险 function Fibonacci2 (n , ac1 = 1 , ac2 = 1) { if( n <= 1 ) {return ac2}; return Fibonacci2 (n - 1, ac2, ac1 + ac2); } Fibonacci2(100) // 573147844013817200000 Fibonacci2(1000) // 7.0330367711422765e+208 Fibonacci2(10000) // Infinity
13. 两个升序数组合并为一个升序数组
function sort (A, B) { var i = 0, j = 0, p = 0, m = A.length, n = B.length, C = [] while (i < m || j < n) { if (i < m && j < n) { C[p++] = A[i] < B[j] ? A[i++] : B[j++] } else if (i < m) { C[p++] = A[i++] } else { C[p++] = B[j++] } } return C }