JS 编程题
阿里面试题(变量赋值)
let a = { n: 1,};let b = a;a.x = a = { n: 2,};console.log(a.x); // undefinedconsole.log(b); // {n: 1, x: {n: 2}}
let a = 12, b = 12;function fn() { // console.log(a, b); // Uncaught ReferenceError: Cannot access 'a' before initialization at fn console.log(b); // 12 let a = (b = 13); console.log(a, b); // 13 13}fn();console.log(a, b); // 12 13
let i = 1;let fn = (i) => (n) => console.log(n + ++i);let f = fn(1);f(2); // 4fn(3)(4); // 8f(5); // 8console.log(i); // 1
var n = 0;function a() { var n = 10; function b() { n++; console.log(n); } b(); return b;}var c = a();c();console.log(n);// 11 12 0
参考js 间断赋值的问题
美团面试题
var obj = { 2: 3, 3: 4, length: 2, push: Array.prototype.push,};obj.push(1);obj.push(2);console.log(obj);// {2: 1, 3: 2, length: 4, push: ƒ} 解析:因为对象的length为2,所以push 1 2 会笼罩2 3 的值// 比照var obj = { length: 2, push: Array.prototype.push,};obj.push(1);obj.push(2);obj.push(3);console.log(obj);// {2: 1, 3: 2, 4: 3, length: 5, push: ƒ}
阿里经典面试题(考查变量晋升/静态方法/实例办法/原型办法调用)
function Foo() { getName = function () { console.log(1); }; return this;}Foo.getName = function () { console.log(2);};Foo.prototype.getName = function () { console.log(3);};var getName = function () { console.log(4);};function getName() { console.log(5);}Foo.getName(); // 2 解析:调用函数的静态方法getName(); // 4 解析:函数表达式会笼罩函数申明式办法Foo().getName(); // 1 解析:调用函数本身的办法getName(); // 1 解析: 受前一行代码执行影响相当于调用this.getName(), 其中this指向window,因为Foo办法外面定义getName的时候没有申明, 所以变成了全局变量new Foo.getName(); // 2 解析:相当于执行new (Foo.getName)()new Foo().getName(); // 3 解析:调用函数的实例办法, 相当于执行(new Foo()).getName()new new Foo().getName(); // 3 解析:相当于执行new (new Foo()).getName)()// 操作运算符的优先级: () > new > .
字节面试题(递归/微工作/宏工作)
function fn() { fn();}fn(); // Uncaught RangeError: Maximum call stack size exceededvar num = 0;function fn() { console.log(num++); setTimeout(fn, 1000);}fn(); // 能够失常执行,为什么?// 解析:起因是因为setTImeout属于异步宏工作,不在主线程栈内存中
字节编程题
const list = [1, 2, 3];const square = (num) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(num * num); }, 1000); });};function test() { list.forEach(async (x) => { const res = await square(x); console.log(res); });}test();// 执行后果: 1s之后输入 1 4 9// 不能批改square办法,实现每隔一秒输入后果const list = [1, 2, 3];const square = (num) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(num * num); }, 1000); });};function test() { list.forEach((x, index) => { setTimeout(async () => { const res = await square(x); console.log(res); }, index * 1000); });}test();
笔者自出的立刻执行函数赋值编程题
var a = 111;(function a() { console.log(a); a = 222; console.log(a);})();console.log(a);// 输入后果:// ƒ a() {// console.log(a);// a = 222;// console.log(a);// }// ƒ a() {// console.log(a);// a = 222;// console.log(a);// }// 111var c = 111;(function c(c) { console.log(c); c = 123; console.log(c);})(c);console.log(c);// 输入后果:// 111// 123// 111
快手面试编程题
实现 add(1)(2)(3)(4)(5).sum()和 add(1)(2, 3)(4)(5).sum()参数不定的累加成果
let add = (...args) => { let foo = (...newArgs) => { return add(...args, ...newArgs); }; foo.toString = () => { return args.reduce((a, b) => a + b); }; foo.sum = () => { return foo.toString(); }; return foo;};// 测试后果:console.log(add(1)(2)(3)(4)(5).sum()); // 15console.log(add(1)(2, 3)(4)(5).sum()); // 15// 优化版代码let add = (...args) => { let foo = (...newArgs) => { return add(...args, ...newArgs); }; foo.sum = () => { return args.reduce((a, b) => a + b); }; return foo;};// 测试后果:console.log(add(1)(2)(3)(4)(5).sum()); // 15console.log(add(1)(2, 3)(4)(5).sum()); // 15
求字符串'(1+2)*3'运算后果(携程面试题)
办法一:应用eval
办法
// 非严格模式下let str = '(1+2)*3';let result = eval(str);console.log(result);// 严格模式下报错:Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'strict-dynamic'
办法二:应用new Funciton
办法
// 非严格模式下let str = '(1+2)*3';function strCalc(str) { return new Function(`return ${str}`)();}let result = strCalc(str);console.log(result);// 严格模式下报错:Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'strict-dynamic'
办法三:利用script
标签内容为可执行代码
let str = '(1+2)*3';function strCalc(str) { let myScript = document.createElement('script'); myScript.innerHTML = `window.golal_calc_result=${str}`; // 把执行后果保留到全局对象 document.body.appendChild(myScript); document.body.removeChild(myScript);}strCalc(str);console.log(window.golal_calc_result);
考查 JS 事件循环微工作和宏工作
console.log(1);setTimeout(function () { console.log(2);}, 0);var promise = new Promise(function (resolve, reject) { console.log(3); setTimeout(function () { console.log(4); resolve(); }, 1000);});promise.then(function () { console.log(5); setTimeout(function () { console.log(6); }, 0);});console.log(7);// 输入后果程序:1 3 7 2 4 5 6// 解析:JS代码执行优先级:主线程 -> 微工作 -> 宏工作
var promise = new Promise(function (resolve, reject) { setTimeout(function () { console.log(1); resolve(); }, 3000);});promise .then(function () { setTimeout(function () { console.log(2); }, 2000); }) .then(function () { setTimeout(function () { console.log(3); }, 1000); }) .then(function () { setTimeout(function () { console.log(4); }, 0); });// 输入后果:3s后输入1和4,再过1s输入3,再过1s输入2// 解析:promise.then()办法要等resolve()执行当前,才会执行前面的then办法,前面的这些办法按定时器异步流程解决
理解更多
async/await 和 setTimeout 以及 promise(字节面试题)
async function async1() { console.log("async1 start"); await async2(); console.log(`async1 end`);}async function async2() { console.log("async2");}console.log("script start");setTimeout(() => { console.log("setTimeout");}, 0);async1();new Promise((resolve, reject) => { console.log("promise1"); resolve();}).then(() => { console.log("promise2");});console.log("script end");// 输入后果:// script start// async1 start// async2// promise1// script end// async1 end// promise2// setTimeout
promise串行问题(腾讯文档)
let promiseArr = [ () => { return new Promise(res => { console.log('run 1', Date.now()); res('run 1 resolve'); }); }, () => { return new Promise(res => { console.log('run 2', Date.now()); res('run 2 resolve'); }); }, () => { return new Promise(res => { console.log('run 3', Date.now()); res('run 3 resolve'); }); },]async function fn () { for (let i = 0; i < promiseArr.length; i++) { // 串行打印console.log; // await promiseArr[i](); // 串行打印console.log并执行resolve await promiseArr[i]().then((value) => { console.log(value); }); }}fn();
事件循环(字节面试题)
function test () { console.log(1); Promise.resolve().then(test);}test();setTimeout(() => {console.log(2)}, 0)// 打印后果:// 始终输入1 不会执行setTimeout外面的回调函数
promise、async/await
async function fn() { let data = await (() => 4)(); console.log(data);}console.log(1);new Promise(resolve => resolve(console.log(2))).then(data => console.log(data));console.log(3);fn();// 打印后果:// 1// 2// 3// undefined// 4// Promise {<fulfilled>: undefined}
// 字节面试题new Promise((reslove, reject) => { reject();}).then(null, () => { console.log(1);}).then(() => { console.log(2);}).then(() => { console.log(3);});// 打印后果: 1 2 3
new Promise((reslove, reject) => { reject();}).then(null, () => { console.log(1);}).then(() => { new Promise((reslove, reject) => { reject(); }).then(null, () => { console.log('a'); }).then(() => { console.log('b'); }).then(() => { console.log('c'); })}).then(() => { console.log(3);})// 打印后果:// 1// a// 3// b// c
new Promise((resolve, reject) => { resolve();}).then(null, () => { console.log(1);}).then(() => { new Promise((resolve, reject) => { console.log(2); resolve(); }).then(null, () => { console.log('a'); }).then(() => { console.log('b'); }).then(() => { console.log('c'); })}).then(() => { console.log(3);})// 打印后果:// 2// 3// b// c
new Promise((resolve, reject) => { reject();}).then(null, () => { console.log(1);}).then(() => { new Promise((resolve, reject) => { console.log(2); reject(); }).then(null, () => { console.log('a'); }).then(() => { console.log('b'); }).then(() => { console.log('c'); })}).then(() => { console.log(3);})// 1// 2// a// 3// b// c
腾讯视频编程题
function foo () { var a = 0; return function () { console.log(a++); }}var f1 = foo(),f2 = foo();f1(); // 0f1(); // 1f2(); // 0
function Page() { console.log(this); return this.hosts;}Page.hosts = ['h1'];Page.prototype.hosts = ['h2'];var p1 = new Page();var p2 = Page();console.log(p1.hosts); // undefinedconsole.log(p2.hosts); // Uncaught TypeError: Cannot read property 'hosts' of undefined
如果让一个不可迭代对象,变成可迭代
var obj = { 0: 0, 1: 1, length: 2,};for (i of obj) { console.log(i);}// 报错:Uncaught TypeError: obj is not iterablevar obj = { 0: 0, 1: 1, length: 2, [Symbol.iterator]: Array.prototype[Symbol.iterator],};for (i of obj) { console.log(i);}// 原理:可迭代对象都领有@@iterator属性
实现深拷贝
罕用的简略实现形式:类型判断+递归
function deepClone(obj) { var newObj = obj instanceof Array ? [] : {}; for (var i in obj) { newObj[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; } return newObj;}// testvar obj = { number: 1, string: "abc", bool: true, undefined: undefined, null: null, symbol: Symbol("s"), arr: [1, 2, 3], date: new Date(), userInfo: { name: "Better", position: "front-end engineer", skill: ["React", "Vue", "Angular", "Nodejs", "mini programs"], }, func: function () { console.log("hello better"); },};console.log(deepClone(obj));
从打印的后果来看,这种实现形式还存在很多问题:这种形式只能实现特定的 object 的深度复制(比方对象、数组和函数),不能实现 null 以及包装对象 Number,String ,Boolean,以及 Date 对象,RegExp 对象的复制。
一行代码实现形式:联合应用JSON.stringify()
和JSON.parse()
var obj = { number: 1, string: "abc", bool: true, undefined: undefined, null: null, symbol: Symbol("s"), arr: [1, 2, 3], date: new Date(), userInfo: { name: "Better", position: "front-end engineer", skill: ["React", "Vue", "Angular", "Nodejs", "mini programs"], }, func: function () { console.log("hello better"); },};var copyObj = JSON.parse(JSON.stringify(obj));console.log(copyObj);
从打印后果能够得出以下论断:
undefined
、symbol
、function
类型间接被过滤掉了date
类型被主动转成了字符串类型
实现一个 bind 函数
原理:应用apply()
或者call()
办法
初始版本
Function.prototype.customBind = function (context) { var self = this; // 保留函数的上下文 var args = [].slice.call(arguments, 1); // 获取自定义bind函数的参数 return function () { args = args.concat([].slice.call(arguments)); // 获取自定义bind函数返回函数传入的参数 return self.apply(context, args); };};var obj = { name: "Better", position: "front-end engineer",};var func = function (age) { console.log("name", this.name); console.log("position", this.position); console.log("age", age);};var f = func.customBind(obj, 18);f();
思考到原型链(最终版)
Function.prototype.customBind = function (context) { // 必须在函数上应用,否则抛出谬误 if (typeof this !== "function") { throw new Error( "Function.prototype.bind - what is trying to be bound is not callable" ); } var self = this; // 保留函数的上下文 var args = Array.prototype.slice.call(arguments, 1); // 获取自定义bind函数的参数 var fNOP = function () {}; var fBound = function () { var bindArgs = Array.prototype.slice.call(arguments); // 获取自定义bind函数返回函数传入的参数 return self.apply( this instanceof fNOP ? this : context, args.concat(bindArgs) ); }; // 这里应用寄生组合继承 fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound;};// 测试var obj = { name: "Better", position: "front-end engineer",};var func = function (age) { console.log("name", this.name); console.log("position", this.position); console.log("age", age);};var f = func.customBind(obj, 18);f();
点击理解更多
性能优化之防抖和节流
对于频繁触发的事件,比方,scroll
、keyup
、mouseover
、resize
等事件,如果不做一些非凡解决的话,可能会影响性能,甚至造成页面卡顿。
防抖和节流就能很好的解决这类问题。
防抖
定义:在规定工夫内,屡次触发事件后,事件处理函数只执行一次,并且是在触发操作完结后执行。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则革除上一次的延时操作定时器,从新定时。
function debounce(fn, wait) { var timeId = null; return function () { var context = this; // 保留绑定事件的对象,如document var args = arguments; // 获取事件参数,如event timeId && clearTimeout(timeId); // 如果规定工夫内(wait)再次触发事件,则革除定时器 timeId = setTimeout(function () { fn.apply(context, args); // 应用apply办法把fn函数的this指向事件对象 }, wait); };}// 测试function func() { console.log(111);}document.addEventListener("mouseover", debounce(func, 1000));
如果心愿立刻执行一次,而后等到进行触发 n 秒后,才能够从新触发执行。
function debounce(fn, wait, immediately) { var timeId = null; return function () { var context = this; var args = arguments; timeId && clearTimeout(timeId); if (immediately) { // 如果曾经执行过,则不再执行 var canExecute = !timeId; timeId = setTimeout(function () { timeId = null; }, wait); if (canExecute) { fn.apply(context, args); } } else { timeId = setTimeout(function () { fn.apply(context, args); // 应用apply办法把fn函数的this指向事件对象 }, wait); } };}// 测试function func() { console.log(111);}document.addEventListener("mouseover", debounce(func, 1000, true));// document.addEventListener('mouseover', debounce(func, 1000));
点击理解更多
节流
定义:触发函数事件后,规定工夫距离内无奈间断调用,只有上一次函数执行后,过了规定的工夫距离,能力进行下一次的函数调用。
原理:如果你继续触发事件,每隔一段时间,只执行一次事件。
对于节流的实现,有两种支流的实现形式,一种是应用工夫戳,一种是设置定时器。
应用工夫戳,当触发事件的时候,咱们取出以后的工夫戳,而后减去之前的工夫戳(最一开始值设为 0 ),如果大于设置的工夫周期,就执行函数,而后更新工夫戳为以后的工夫戳,如果小于,就不执行。
// 应用工夫戳function throttle(fn, wait) { var prev = 0; return function () { var context = this; var args = arguments; var now = new Date().getTime(); // if (!prev) prev = now; if (now - prev > wait) { // 如果工夫距离大于wait,执行函数 fn.apply(context, args); prev = now; // 把以后工夫赋值给前一个工夫 } };}// 测试function func() { console.log(111);}document.addEventListener("mouseover", throttle(func, 1000));
应用定时器:当触发事件的时候,咱们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执行,而后执行函数,清空定时器,这样就能够设置下个定时器。
// 应用定时器function throttle(fn, wait) { var timeId = null; return function () { var context = this; var args = arguments; if (!timeId) { // 如果没有定时器 timeId = setTimeout(function () { fn.apply(context, args); timeId = null; }, wait); } };}// 测试function func() { console.log(111);}document.addEventListener("mouseover", throttle(func, 1000));
总结:
- 第一种事件会立即执行,第二种事件会在 n 秒后第一次执行
- 第一种事件进行触发后没有方法再执行事件,第二种事件进行触发后仍然会再执行一次事件
点击理解更多
应用 setTimeout 实现 setInterval 性能
咱们平时开发中尽量避免应用 setInterval 反复定时器,这种反复定时器的规定有两个问题:
- 某些距离会被跳过
- 多个定时器的代码执行工夫可能会比预期小
var i = 0;function count() { console.log(i++); setTimeout(count, 1000);}setTimeout(count, 1000);
或者应用 arguments.callee
var i = 0;setTimeout(function () { // do something console.log(i++); setTimeout(arguments.callee, 1000);}, 1000);
如何实现 sleep 成果
办法一:应用 promise
function sleep(time) { return new Promise(function (resolve, reject) { console.log("start"); setTimeout(function () { resolve(); }, time); });}sleep(1000).then(function () { console.log("end");});// 先输入start,提早1000ms后输入end
办法二:应用 async/await
function sleep(time) { return new Promise(function (resolve, reject) { setTimeout(function () { // do something resolve(); }, time); });}async function test() { console.log("start"); var result = await sleep(1000); console.log("end"); return result;}test(); // 先输入start,提早1000ms后输入end
办法三:应用 generate
function* sleep(time) { yield new Promise((resolve, reject) => { console.log("start"); setTimeout(() => { // do something resolve(); }, time); });}sleep(1000) .next() .value.then(() => { console.log("end"); }); // 先输入start,提早1000ms后输入end
如何实现 a == 1 && a == 2 && a == 3 为 true
办法一:联合应用数组的toString()
和shift()
办法
var a = [1, 2, 3];// a.join = a.shift;// a.valueOf = a.shift;a.toString = a.shift;console.log(a == 1 && a == 2 && a == 3); // true
原理:当简单类型数据与根本类型数据作比拟时会产生隐性转换,会调用toString()
或者valueOf()
办法
办法二:原理和办法一一样都是批改toString()
办法
var a = { value: 1, toString: function () { return a.value++; },};console.log(a == 1 && a == 2 && a == 3); // true
实现 add(1)(2)(3)这类办法以及扩大办法
// 一般写法var add = function (a) { return function (b) { return function (c) { return a + b + c; }; };};console.log(add(1)(2)(3)); // 6// 扩大写法function addExtend(x) { var sum = x; var temp = function (y) { sum = sum + y; return temp; }; temp.toString = function () { return sum; }; return temp;}console.log(addExtend(1)(2)(3)); // ƒ 6console.log(typeof addExtend(1)(2)(3)); // functionconsole.log(Number(addExtend(1)(2)(3))); // 6console.log(Number(addExtend(1)(2)(3)(4)(5))); // 15
闭包和工作队列例子
for (var i = 0; i < 5; i++) { setTimeout( (function (i) { console.log(i); })(i), i * 1000 );}// 测试后果: 立刻输入0 1 2 3 4
for (var i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, i * 1000);}// 测试后果: 立刻输入5 而后每隔一秒输入5 总共输入5次
for (let i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, i * 1000);}// 测试后果:立刻输入0 而后每隔一秒别离输入1 2 3 4
应用正则表达式匹配 url 参数键值对(兼容 url 中蕴含多个?和#号)
let reg = /([^?&#]+=[^?&#]+)/g;let str = "https://c2b.brightoilonline.com/bdh5/channel.html?chelun_params=ad0bb3e5fc3b3bfeb9b53cc9686eb1aaaecb8a53e9f4a77c5ed68714123b25913219200cba48d9044c7b48325436960f42c1cde18f349ef63ab53ee791970243a8ba79f9a2dc8aa1#/chelunGasList?pcode=c2b8g717rkj603o15005&fromApp=true";console.log(str.match(reg));// 测试后果:["chelun_params=ad0bb3e5fc3b3bfeb9b53cc9686eb1aaaecb…f42c1cde18f349ef63ab53ee791970243a8ba79f9a2dc8aa1", "pcode=c2b8g717rkj603o15005", "fromApp=true"]str = "https://c2b-test2.brightoilonline.com/bdh5/channel.html#/chelungaslist?pcode=c2b0293jm44x97an6339&fromApp=true";console.log(str.match(reg));// 测试后果: ["pcode=c2b0293jm44x97an6339", "fromApp=true"]str = "https://c2b-test2.brightoilonline.com/bdh5/channel.html?pcode=c2b0293jm44x97an6339&fromApp=true";console.log(str.match(reg));// 测试后果: ["pcode=c2b0293jm44x97an6339", "fromApp=true"]
解析 URL Params 为对象
let url = "http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled";parseParam(url);/* 后果{ user: 'anonymous', id: [ 123, 456 ], // 反复呈现的 key 要组装成数组,能被转成数字的就转成数字类型 city: '北京', // 中文需解码 enabled: true, // 未指定值得 key 约定为 true}*/function parseParam(url) { const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 前面的字符串取出来 const paramsArr = paramsStr.split("&"); // 将字符串以 & 宰割后存到数组中 let paramsObj = {}; // 将 params 存到对象中 paramsArr.forEach((param) => { if (/=/.test(param)) { // 解决有 value 的参数 let [key, val] = param.split("="); // 宰割 key 和 value val = decodeURIComponent(val); // 解码 val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字 if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则增加一个值 paramsObj[key] = [].concat(paramsObj[key], val); } else { // 如果对象没有这个 key,创立 key 并设置值 paramsObj[key] = val; } } else { // 解决没有 value 的参数 paramsObj[param] = true; } }); return paramsObj;}// 进阶:应用原生URLSearchParams对象function optParseQuery(url) { const u = new URL(url) const sp = new URLSearchParams(u.search) return sp.entries()}console.log(optParseQuery(url))// {// "user": "anonymous",// "id": "456",// "city": "北京",// "enabled": ""// }
数组对象去重
/*** @param {Array} arr 去重的数组对象* @param {String} key 依据key进行去重* @return {Array} 去重后的数组对象*/// 办法一function uniqueArrObjByKey (arr, key) { const map = Object.create(null) const res = [] arr.forEach(item => { if (!map[item[key]]) { map[item[key]] = true res.push(item) } }) return res}// 办法二function uniqueArrObjByKey (arr, key) { const map = Object.create(null) const res = arr.reduce((cur, next) => { map[next[key]] ? '' : map[next[key]] = true && cur.push(next) return cur }, []) // 设置cur默认类型为数组,并且初始值为空的数组 return res}// 测试var arr = [{name: '廖小新', age: 18}, {name: '廖小物', age: 18}, {name: '廖小新', age: 20}, {name: '廖小物', age: 18}, {name: '廖小念', age: 18}]console.log(uniqueArrObjByKey(arr, 'name'))console.log(uniqueArrObjByKey(arr, 'age'))
给定两个数组,编写一个函数来计算它们的交加
阐明:
- 输入后果中的每个元素肯定是惟一的。
- 咱们能够不思考输入后果的程序。
// 办法一:应用filter和set办法function findIntersection(arr1, arr2) { return [...new Set(arr1.filter((item) => arr2.includes(item)))];}var arr1 = [1, 2, 2, 3];var arr2 = [2, 3, 3, 4];findIntersection(arr1, arr2); // [2, 3]// 办法二:应用map哈希表function findIntersection(arr1, arr2) { var res = new Set(); var set1 = new Set(arr1); var set2 = new Set(arr2); for (let item of set2) { if (set1.has(item)) { res.add(item); } } return [...res];}var arr1 = [1, 2, 2, 3];var arr2 = [2, 3, 3, 4];findIntersection(arr1, arr2); // [2, 3]function findIntersection(arr1, arr2) { var map = {}; var res = []; arr1.forEach((item) => { map[item] = true; }); arr2.forEach((item) => { if (map[item]) { res.push(item); } }); res = [...new Set(res)]; return res;}var arr1 = [1, 2, 2, 3];var arr2 = [2, 3, 3, 4];findIntersection(arr1, arr2); // [2, 3]// 扩大求三个数组的交加function findThreeIntersection(arr1, arr2, arr3) { const map1 = new Set(arr1); const map2 = new Set(arr2); const map3 = new Set(arr3); const res = []; arr1.forEach((item) => { if (map2.has(item) && map3.has(item)) { res.push(item); } }); return [...new Set(res)];}var arr1 = [1, 2, 2, 3, 5];var arr2 = [2, 3, 3, 4, 3, 5];var arr3 = [1, 2, 3, 3, 4, 5];findThreeIntersection(arr1, arr2, arr3); // [2, 3]
更多汇合操作参考 Set
es6 尾调用-尾递归
求正整数n的阶乘
function factorial (n) { if (n === 1) return 1 return n * factorial(n - 1)}console.time()factorial(1000)console.timeEnd()// default: 1.697998046875 ms
// 应用尾递归function factorial (n, total) { if (n === 1) return total return factorial(n - 1, n * total) }console.time()factorial(1000, 1)console.timeEnd()
es6 尾调用-尾递归
本文由mdnice多平台公布