常见前端面试代码题
一、this绑定
//this绑定,立即执行函数表达式 var num = 1; var myObject = { num:2, add:function(){ this.num = 3; (function(){ console.log(this.num); this.num = 4; })(); console.log(this.num); }, sub:function(){ console.log(this.num); } } myObject.add(); console.log(myObject.num); console.log(num); var sub = myObject.sub; sub(); //结果 1 3 3 4 4
var number = 5; var obj = { number: 3, fn1: (function () { var number; this.number *= 2; number = number * 2; number = 3; return function () { var num = this.number; this.number *= 2; console.log(num); number *= 3; console.log(number); } })() } var fn1 = obj.fn1; fn1.call(null); obj.fn1(); console.log(window.number); //结果 10 9 3 27 20
二、函数调用(函数表达式、箭头函数)
var name = 'window' var person1 = { name:'person1', show1:function(){ console.log(this.name); }, show2:()=>console.log(this.name), show3:function(){ return function(){ console.log(this.name); } }, show4:function(){ return ()=>console.log(this.name) } } var person2 = {name:'person2'}; person1.show1();//person1 person1.show1.call(person2);//person2 person1.show2();//window person1.show2.call(person2);//window person1.show3()();//person1错 window person1.show3().call(person2);//person2 person1.show3.call(person2)();//person2错 window person1.show4()();//window错 person1 person1.show4().call(person2);//person1 person1.show4.call(person2)();//window错 person2
var name = "hanmeimei"; var f = function(){ var name = "lilei"; return function(){ console.log(this.name); } } f()();//hanmeimei
三、10个随机数,不重复
function getRandom(num){ var numb = []; var newArr = []; while(numb.length<num){ let n = parseInt(Math.random() * 32); if(n>=2&&n<=32){ numb.push(n); newArr = Array.from(new Set(numb)); } } console.log(newArr); //return newArr; } getRandom(10);
四、数组展开函数
// 写出一个数组展开函数, 如输入:[1,[2,[3,4,2],2],5,[6]], 则输出:[1,2,3,4,2,2,5,6] // 因为和深度无关,所以说最简单可以这样 function flatten(arr){ var res = arr.join().split(','); res = res.map( ele => +ele) return res; } // 还有吗,递归,写一下 function flatten(arr){ var array = []; arr.forEach(ele => { if(Array.isArray(ele)){ array.push(...flatten(ele)); } else { array.push(ele); } }) return array; } var arr1 = [1,[2,[3,4,2],2],5,[6]]; flatten(arr1)
五、eventloop
console.log('begin'); setTimeout(() => { console.log('setTimeout 1'); Promise.resolve().then(() => { console.log('promise 1'); setTimeout(() => { console.log('setTimeout2 between promise1&2'); }) }).then(() => { console.log('promise 2'); }); }, 0); console.log('end');
begin
end
setTimeout 1
promise 1
promise 2
setTimeout2 between promise1&2
console.log('script start') async function async1() { await async2() console.log('async1 end') } async function async2() { console.log('async2 end') } async1() setTimeout(function() { console.log('setTimeout') }, 0) new Promise(resolve => { console.log('Promise') resolve() }) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') }) console.log('script end') //结果 script start end Promise end end promise1 promise2 undefined setTimeout
六、基本数据类型判断
console.log(Number([1])) if([]==false){console.log(1)}//1 if({}==false){console.log(2)} if([]){console.log(3)}//3 if([1]==[1]){console.log(4)}
七、裴波纳锲数列
function Fibonacci(n) { if (n == 0) { return 1; } var pre = 1, // 前一个值 cur = 1; // 当前值 for (var i = 2; i <= n; i++) { // 更新两个值 cur += pre; pre = cur - pre; } return cur; } function Fibonacci2(n) { var f = [0, 1]; for(let i = 2; i <= n; i++) { f[i] = f[i - 1] + f[i - 2]; } return f[n]; } Fibonacci(5)
function fibonacci(n){ if(n==1||n==2) return 1; return fibonacci(n-1)+fibonacci(n-2); }
八、读取url中的参数
var getUrlParam2 = function(sUrl, sKey){ // 捕获组两枚,一枚负责Key 一枚负责获取Value var reg = new RegExp('([0-9a-zA-Z%]+)=([0-9a-zA-Z%]+)&*', 'ig'); // 结果集保存 var result = {}; var temp; var key, value; while(temp = reg.exec(sUrl)) { key = temp[1]; value = temp[2]; if (result[key] && !(result[key] instanceof Array)) { result[key] = [result[key], value]; // 如果发现了第二个同名参数,则从字符串变为数组 } else if (result[key] instanceof Array) { result[key].push(value); // 已经是数组,又找到了,就push进去 } else { result[key] = value; // 第一次,还是普通保存 } } if (sKey) { return result[sKey] ? result[sKey] : ''; // 为了避免undefined的情况 } else { return result; // 返回全部的对象参数 } } getUrlParam2("http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe")
九、jsonp
//http://www.baidu.com?aa=11&callback=my_jsonp04349289664328899 var jsonp = function(url,param,callback){ //处理url地址,查找?,如果没有?这个变量就有一个"?",有?这个变量接收一个& var querystring = url.indexOf("?") == -1?"?":"&"; //处理参数{xx:xx} for(var k in param) { querystring += k + "=" + param[k] + '&';//?k=para[k] } //处理回调函数名 var random = Math.random().toString().replace(".",""); var cbval = "my_jsonp" + random; var cb = "callback="+cbval; querystring += cb; var script = document.createElement("script"); script.src = url + querystring; //把回调函数的名字附给window window[cbval] = function(param) { //这里执行回调的操作,用回调来处理参数 callback(param); //拿到了就删掉这个script document.body.removeChild(script); }; document.body.appendChild(script); } jsonp( "https://www.baidu.com", {aa:11}, function(){ console.log(param); } );
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> // 得到航班信息查询结果后的回调函数 var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); }; // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); </script> </head> <body> </body> </html>
十、深克隆
//js的深克隆 function deepCopy(obj){ //判断是否是简单数据类型, if(typeof obj == "object"){ //复杂数据类型 var result = obj.constructor == Array ? [] : {}; for(let i in obj){ result[i] = typeof obj[i] == "object" ? deepCopy(obj[i]) : obj[i]; } }else { //简单数据类型 直接 == 赋值 var result = obj; } return result; }
十一、判断是否是数组
//判断是否为数组 通过toString()方法 通过constructor 通过instanceof Array.isArray var arr = [1, 2, 3]; var obj = { name: 'lyl', age: 18, 1: 'name' } console.log(Object.prototype.toString.call(arr) === '[object Array]'); //true console.log(Object.prototype.toString.call(boj) === '[object Array]'); //false
十二、promise
// 这里我们创建了一个构造函数 参数就是执行器 function Promise(exector) { // 这里我们将value 成功时候的值 reason失败时候的值放入属性中 let self = this; // 这里我们加入一个状态标识 this.status = 'pending'; this.value = undefined; this.reason = undefined; // 成功执行 function resolve(value) { // 判断是否处于pending状态 if (self.status === 'pending') { self.value = value; // 这里我们执行之后需要更改状态 self.status = 'resolved'; } } // 失败执行 function reject(reason) { // 判断是否处于pending状态 if (self.status === 'pending') { self.reason = reason; // 这里我们执行之后需要更改状态 self.status = 'rejected'; } } // 这里对异常进行处理 try { exector(resolve, reject); } catch(e) { reject(e) } } // 我们将then方法添加到构造函数的原型上 参数分别为成功和失败的回调 Promise.prototype.then = function(onFulfilled, onRejected) { // 获取下this let self = this; if (this.status === 'resolved') { onFulfilled(self.value); } if (this.status === 'rejected') { onRejected(self.reason); } } //运行 let promise = new Promise((resolve, reject) => { resolve("haha"); }) promise.then(data => { console.log(data); //输出 haha }, err=> { console.log(err); }) // 多次调用 promise.then(data => { console.log(data); //输出 haha }, err=> { console.log(err); })
//完整版实现 function MyPromise (executor) { var self = this; self.status = 'pending'; self.resolveValue = null; self.rejectReason = null; self.ResolveCallBackList = []; self.RejectCallBackList = []; function resolve (value) { if (self.status === 'pending') { self.status = 'Fulfilled'; self.resolveValue = value; self.ResolveCallBackList.forEach(function (ele) { ele(); }); } } function reject (reason) { if (self.status === 'pending') { self.status = 'Rejected'; self.rejectReason = reason; self.RejectCallBackList.forEach(function (ele) { ele(); }); } } try { executor(resolve, reject); }catch(e) { reject(e); } }; function ResolutionRetrunPromise (nextPromise, returnValue, res, rej) { if (returnValue instanceof MyPromise) { // Promise 对象 returnValue.then(function (val) { res(val); }, function (reason) { rej(reason) }); }else { res(returnValue); } } MyPromise.prototype.then = function (onFulfilled, onRejected) { if (!onFulfilled) { onFulfilled = function (val) { return val; } } if (!onRejected) { onRejected = function (reason) { throw new Error(reason); } } var self = this; var nextPromise = new MyPromise(function (res, rej) { if (self.status === 'Fulfilled') { setTimeout(function () { try { // var nextResolveValue = onFulfilled(self.resolveValue); // res(nextResolveValue); var nextResolveValue = onFulfilled(self.resolveValue); ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej); }catch(e) { rej(e); } }, 0); } if (self.status === 'Rejected') { setTimeout(function () { try { var nextRejectValue = onRejected(self.rejectReason); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej); }catch(e) { rej(e); } }, 0); } // if (self.status === 'pending') { self.ResolveCallBackList.push(function () { try { var nextResolveValue = onFulfilled(self.resolveValue); ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej); }catch(e) { rej(e); } }); self.RejectCallBackList.push(function () { setTimeout(function () { try { var nextRejectValue = onRejected(self.rejectReason); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej); }catch(e) { rej(e); } }, 0); }); } }); return nextPromise; }; MyPromise.prototype.catch = function (onRejected) { return this.then(null, onRejected); }; MyPromise.prototype.finally = function (callback) { return this.then(function (data) { callback(); return data; }, function (reason) { callback(); throw reason; }); }; MyPromise.all = function (promiseArr) { // console.log(0) return new MyPromise(function (res, rej) { // promiseArr 所有的值都看一下, 如果全都是成功 res // rej // then var arr = []; var times = 0; function processResult (index, result) { arr[index] = result; times++; // arr.length == promiseArr.length if (times == promiseArr.length) { res(arr); } }; for (let i = 0; i < promiseArr.length; i++) { var oPromise = promiseArr[i]; if (typeof oPromise.then == 'function') { oPromise.then(function (val) { // val // 我要存一下这个val val -> arr -> i processResult(i, val) }, function (reason) { // reason rej(reason); }) }else { processResult(i, oPromise); } } }); }; MyPromise.race = function(promiseArr) { return new MyPromise(function (resolve, reject) { promiseArr.forEach(function (promise, index) { promise.then(resolve, reject); }); }); }; MyPromise.reject = function (reason) { return new MyPromise(function (resolve, reject) { reject(reason); }); }; MyPromise.resolve = function (val) { return new MyPromise(function (resolve, reject) { resolve(val); }); };
十三、JS如何判断一组数字是否连续
// 当出现连续数字的时候以‘-’输出 [1, 2, 3, 4, 6, 8, 9, 10] // 期望结果 ["1-4", 6, "8-10"] var arrange = function(arr){ var result = [],temp = []; arr.sort(function(source, dest){ return source - dest; }).concat(Infinity).reduce(function(source, dest){ temp.push(source); if(dest-source > 1){ result.push(temp); temp = []; } return dest; }); return result; }; var formatarr = function(arr) { var newArr = [] var arr1 = arrange(arr) for (var i in arr1) { var str = ''; if (arr1[i].length > 1) { str = arr1[i][0] + '-' + arr1[i][arr1[i].length - 1]; newArr.push(str) } else { newArr.push(arr1[i][0]); } } return newArr; }
十四、请自定义一个函数,实现字符串反转。
function revStr(str){ var temStr = ""; var len = str.length; for(var i=len-1;i>=0;i--){ temStr = str.charAt(i); } return temStr; } //字符串的完全翻转 str.split("").reverse().join("") //翻转字符串中单词顺序,但单词字母顺序不变,注意:单词间可能有多空格,并且前后可能也有空格 function reverseStr(param){ var arr = param.split(/\s+/); var newArr = []; for(i=0;i<arr.length;i++){ newArr[arr.length-i] = arr[i]; } return newArr.join(" ").trim(); } document.write(reverseStr("smile at life"));
十五、JavaScript中如何检测一个变量是一个string/数组类型?
var str = "hello world";
function isString(str){
if(typeof str == "string" || str.constructor == String){
return true;
}else{
return false;
}
}
if(typeof Array.isArray==='undefined'){
Array.isArray=function(arg){
return Object.prototype.tostring.call(rag)==='[Object Array]';
};
}
十六、找到第一个数组array1中出现,而在第二个数组array2中没有出现的数字
function findNullOfNum(arr1,arr2){ var str = arr2.split(""); var result = []; for(var i=0,x=0;i<arr1.length;i++){ if(str.indexOf(arr1[i] == -1){ result[x] = arr1[i]; x++; } } return result; }
十七、数组去重
function select(arr){ var temp=[]; for(var i = 0;i < arr.length;i++){ //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。ie8不兼容 if(temp.indexOf(arr[i]) == -1){ temp.push(arr[i]); } } return temp; } //具体验证 var arr=[4,5,1,53,5,1,3]; console.log(select(arr)); //includes():判断当前数组是否包含某个值,若有则返回true,若没有则返回false; function select(arr){ var temp=[]; arr.forEach((v)=>{ temp.includes(v)||temp.push(v); }) return temp; } //循环判断 function select(arr){ var temp=[]; for(var i = 0; i < arr.length; i++){ for(var j = i+1; j < arr.length; j++){ if(arr[i] === arr[j]){ j = ++i; } } temp.push(arr[i]); } return temp; }
//输入[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN] //输出[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a'] Array.prototype.uniq = function () { var resArr = []; var flag = true; for(var i=0;i<this.length;i++){ if(resArr.indexOf(this[i]) == -1){ if(this[i] != this[i]){ //排除 NaN if(flag){ resArr.push(this[i]); flag = false; } }else{ resArr.push(this[i]); } } } return resArr; }
十八、字符串全排列
function Permutation(str) { let res=[]; if(str.length<=0) return res; arr=str.split("");//将字符串转化为字符数组 res=permutate(arr,0,res); res=[...new Set(res)];//去重 res.sort();//排序 return res; } function permutate(arr,index,res){ if(arr.length==index){ let s=""; for(let i=0;i<arr.length;i++){ s+=arr[i]; } return res.push(s); }else{ for(let i=index;i<arr.length;i++){ [arr[index],arr[i]]=[arr[i],arr[index]];//交换 permutate(arr,index+1,res); [arr[index],arr[i]]=[arr[i],arr[index]];//交换 } } return res; }
十九、找出数组中重复数字
function findSame(arr) { let map = {}, res=[]; for (let i = 0; i < arr.length; i++) { if (!map[arr[i]]) { map[arr[i]] = 1; } else { map[arr[i]]++; } } for (let i in map) { if (map[i] > 1) { res.push(i); } } return res; }
二十、转换obj
var obj =[ {id: 1, parent: null}, {id: 2, parent: 1}, {id: 3, parent: 2}, ] function transform(obj, index) { let node; if(obj.length - 1 == index){ node = { id: obj[index].id, parent: obj[index].parent } }else{ node = { id: obj[index].id, parent: obj[index].parent, child: transform(obj,++index) } } return node; } let obj2 = { obj: transform(obj, 0) } console.log(obj2);
二十一、实现log函数
function log(...args){ let str = args.join(" "); return "(app)"+str; }
二十二、动态插入p标签
let p = document.createElement("p"); p.setAttribute("class", "pdd-slogan"); p.textContent = "多拼多实惠" div.appendChild(p); document.body.appendChild(div);
二十三、let a = new A("test");发生了什么?(笔试简答题)
1.先对A构造函数RHS查询标识符。
2.使用new 调用构造函数A
//创建一个新的对象,并设置__proto__
//将构造函数的作用域赋值给新对象(因此this就指向了这个新对象)
//执行函数中的代码(为这个对象添加新的属性)
//返回这个新的对象
//将构造函数的作用域赋值给新对象(因此this就指向了这个新对象)
//执行函数中的代码(为这个对象添加新的属性)
//返回这个新的对象
3.创建变量a,并把之前的调用结果赋值给变量a
下面是new的原理实现
//实现一个new方法 function New(f) { //返回一个func return function () { var o = {"__proto__": f.prototype}; f.apply(o, arguments);//继承父类的属性 return o; //返回一个Object } }
二十四、输入一个数字,不以0开头,找到相同数字组合的最小数字
function nextSmaller (num) { // your code here 例:输入:210215,输出:101225 输入:21,输出:12 找不到满足的输出-1 var arr = num.toString().split(""); if(arr[0]!=0){ arr.sort(); console.log(arr); var i = 0; while(arr[i]==0){ i = i+1; } if(i!=0){ arr[0] = arr[i]; arr[i] = 0; } if(num>=parseInt(arr.join(""))){ return parseInt(arr.join("")); }else{ return -1; } }else{ return -1; } }
二十五、图片懒加载和预加载
function throttle(fn, delay, atleast) {//函数绑定在 scroll 事件上,当页面滚动时,避免函数被高频触发, var timeout = null,//进行去抖处理 startTime = new Date(); return function() { var curTime = new Date(); clearTimeout(timeout); if(curTime - startTime >= atleast) { fn(); startTime = curTime; }else { timeout = setTimeout(fn, delay); } } } function lazyload() { var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function() { var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) { if(images[i].offsetTop < seeHeight + scrollTop) { if(images[i].getAttribute('src') === 'images/loading.gif') { images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首页的页面图片 window.addEventListener('scroll', throttle(loadImages, 500, 1000), false); //函数节流(throttle)与函数去抖(debounce)处理, //500ms 的延迟,和 1000ms 的间隔,当超过 1000ms 未触发该函数,则立即执行该函数,不然则延迟 500ms 执行该函数
/** * 遍历imgs数组,将所有图片加载出来 * 可以通过控制台查看网络请求,会发现所有图片均已加载 */ for (let i = 0; i < len; i++) { let imgObj = new Image(); // 创建图片对象 imgObj.src = imgs[i]; imgObj.addEventListener('load', function () { // 这里没有考虑error,实际上要考虑 console.log('imgs' + i + '加载完毕'); }, false); }
二十六、二叉树前序遍历
function Node (data, left, right) { this.data = data; this.left = left; this.right = right; this.show = function () { return this.data; }; } function BST () { this.root = null; this.insert = function (data) { var node = new Node(data, null, null); if (this.root === null) { this.root = node; } else { var current = this.root; var parent; while (true) { parent = current; if (data < current.data) { current = current.left; if (current === null) { parent.left = node; break; } } else { current = current.right; if(current === null) { parent.right = node; break; } } } } }; // 中序遍历 this.inOrder = function (node) { if (node !== null) { this.inOrder(node.left); console.log(node.show()); this.inOrder(node.right); } }; // 先序遍历 this.preOrder = function (node) { if (node !== null) { console.log(node.show()); this.preOrder(node.left); this.preOrder(node.right); } }; // 后序遍历 this.afterOrder = function (node) { if (node !== null) { this.afterOrder(node.left); this.afterOrder(node.right); console.log(node.show()); } }; this.getMin = function () { var current = this.root; while (current.left !== null) { current = current.left; } return current.data; }; this.getMax = function () { var current = this.root; while (current.right !== null) { current = current.right; } return current.data; }; this.find = function (data) { var current = this.root; while (current !== null) { if (data < current.data) { current = current.left; } else if (data > current.data) { current = current.right; } else { return current; } } return null; }; this.remove = function (data) { this.root = this._removeNode(this.root, data); //将根节点转换 }; this._getSmallest = function (node) { while(node.left!=null){ node=node.left; } return node; }; this._removeNode = function (node, data) { if (node === null) { return null; } if (data === node.data) { // 如果没有子节点 if (node.right === null && node.left === null) { return null; } // 如果没有左子节点 if (node.left === null) { return node.right;//直接指向其右节点 } // 如果没有右子节点 if (node.right === null) { return node.left; } // 如果有两个节点 if (node.right !== null && node.left !== null) { var tempNode = this._getSmallest(node.right); // 找到最小的右节点 node.data = tempNode.data; node.right = this._removeNode(node.right, tempNode.data); // 依次寻找 return node; } } else if (data < node.data){ node.left = this._removeNode(node.left, data); return node; } else { node.right = this._removeNode(node.right, data); return node; } }; }
二十七、js大数相加
原文连接:https://blog.csdn.net/u013362969/article/details/86544785
function add (str1, str2) { let len1 = str1.length; let len2 = str2.length; // let len = len1<len2 ? len1 : len2; let len = Math.max(len1, len2); let res = ''; let jin = 0; for (let i = 0; i < len; i++) { let ad1 = str1.charAt(len1 - i - 1) ; let ad2 = str2.charAt(len2 - i - 1) ; //str1.charAt(-1)==='';Number('')===0; let sum = Number(ad1) + Number(ad2) + jin; res = sum % 10 + res; jin=sum>9 // jin = Math.floor(sum / 10); } return res.replace(/^0+/, ''); }; function addBigNumber(a, b) { var res = '', temp = 0; a = a.split(''); b = b.split(''); while (a.length || b.length || temp) { temp += ~~a.pop() + ~~b.pop(); res = (temp % 10) + res; temp = temp > 9; } return res.replace(/^0+/, ''); }
二十八、sort方法将数组内的对象进行排序
var presonArr = [ { name:'freddy', age:24, score:97 }, { name:'nick', age:18, score:87 }, { name:'mike', age:26, score:80 }, { name:'james', age:34, score:90 }, { name:'curry', age:30, score:83 } ]; //年龄升序排序 presonArr.sort(function(a,b){ return a.age - b.age; }); console.log(presonArr);
后续会继续补充······