一、Math
-
1、Math.ceil()
- 分页计算 Math.ceil()。求得最大上限整数值
有每页显示的条数,和改元素的序号,求改元素所在的页码数。 const index = 4 // 下标是从0开始的,所以加1 const pageSize = 10 // 每页显示的条数。 const pageNum = Math.ceil((index + 1)/pageSize) -
2、Math.max() 求数组的最值
const a = [1,2,3,4,5] const max = Math.max(...a) //需要展开 5 const max2 = Math.max(a) //不展开的话 NaN -
3、Math.random()和Math.round()
- random 生成0-1的随机数
- round 四舍五入一个最近的整数。
// 生成20-30的随机整数 const random20 = Math.round(20 + Math.random()*10) -
4、Math.floor()和Math.sqrt()
- Math.floor() 向下取整、返回=<参数。
- Math.floor(-5.9) // -6
- Math.floor(0.6) // 0
- Math.floor(0.4) // 0
- Math.sqrt() 平方根必须是正数
- var d=Math.sqrt(0.64); // 0.8
判断一个数是否是素数 素数:大于1的自然数,不可以被自然整数(除了1和自己)整除的数。 function is_prime(n){ if (n <= 1){ return fales } const N = Math.floor(Math.sqrt(n)); let is_prime = true; for(let i = 2; i <= N; i++){ if(n % i === 0 ){ is_prime = false; break; } } return is_prime } - Math.floor() 向下取整、返回=<参数。
二、Array
-
Array.lenght 长度
-
Array.indexOf() 获取元素的序号。
- [1,2,3].indexOf(2) 1
-
Array.isArray: 判断是是否是数组
- Array.isArray([]) true
-
forEach 遍历
- 和for循环类似,不能break
-
push/pop/shift/unshift
- push 数组尾部添加
- pop 删除最后一个元素并返回此元素,原来数组改变了长度和内容。
- [1,2,3].pop() // 3 ,[1,2,3] 变成了[1,2]
- shift 删除第一个元素并返回此元素,原来数组改变了长度和内容
- [1,2,3].shift() // 1, 原数组变成可[2,3]
- unshift 往数组头部添加元素,并返回长度值
- [1,2,3].unshift('add') // 4,原来数组变成了 ['add',1,2,3]
-
map/reduce/reduceRight
- reduce :两两处理,前2个的处理结果作为一个参数的值
- [1,2,3].reduce((x,y) => x+y) ;// 6
- 1+2=3(3成了第一个参数x,第三个参数成了y,依次类推),3+3=6
- reduceRight 从右往左同reduce。
- reduce :两两处理,前2个的处理结果作为一个参数的值
-
filter
- [1,2,3].filter(x=>x>2) //3
-
from 类数组对象或者可遍历的对象转换正一个数组;第二参数(fun)作用相当于map,
- 字符串转换数组
let str = 'hello world!'; console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"] -
slice(start,end) 剪切,不会改变原来数组,返回新的数组,start必选,如果是-1是最后一个元素,-1是倒数第二个元素,依次类推
- console.log([1,2,3].slice(0,1)) // [1]
- console.log([1,2,3,4].slice(-1)) // [4]
- console.log([1,2,3,4].slice(-3,-1)) //[2, 3]
-
splice(index,howmany,...others) index:位置,howmany要处理的数量;others新的项目。会修改原来的数组。
- 插入:
- let arr = [1,2,3]; arr.splice(2,0,'ee') // arr = [1,2,'ee',3]
- 替换:
- let arr = [1,2,3]; arr.splice(2,1,'bb') // arr = [1,2,'bb']
- 删除并添加:
let arr = [1,2,3,4,5,6]; arr.splice(2,3,'cc') // 从下标为2开始删除3个元素,然后添加‘cc’[1,2,'cc',6]
- 插入:
-
sort(fun) 排序
- let b = [1,32,43,4,3,545] b.sort() //[1, 3, 32, 4, 43, 545]
let arr = [23,4,32,33] function sortNumber(a,b) { return a - b } arr.sort(sortNumber)- 中文排序
['王文成','王峰','蒋雪','李明'].sort((a,b) => a.localeCompare(b, 'zh')) -
every(fun) 检测数组中的每个元素是否符合函数提供的条件。如果一个元素不满足,return false,剩余的元素不在检测。
var ages = [32, 33, 16, 40];
function checkAdult(age) {
return age >= 18;
}
function myFunction() {
document.getElementById("demo").innerHTML = ages.every(checkAdult);
}
// false
* 改变原来数组的方法:pop,push,shift,unshift,splice,sort,reverse
* 不改变原来数组的方法:concat(),join(),forEach(),slice(),toString(),map,filter,some,every
三、迭代器和生成器
- 迭代器iterator 是一种设计模式,它提供了一种遍历内容的方法,不需要关心内部的构造。生成器(generator)本身也是一种设计模式,用于构造复杂对象,js中的生成器用于构造迭代器。
- 优势:
- 简化语法(树)
- 节省空间
- 分散执行片段(节省单位时间处理量)(对于单线程的前端很重要)
- 构造异步语法。
- 参考函数库ranmda
const s = new Set([1,2,3,4,5]);
const it = s.values();
console.log(it);
// SetIterator { 1, 2, 3, 4, 5}
- while取值
// 跌代器取值1
const s = new Set([1,2,3,4,5]);
const it1 = s.values();
let val = null;
while( !(val = it1.next()).done ){
console.log(val);
// 有bug
// 不会出现{value:1,done:false}.
}
- ...展开符取值
// 跌代器取值2
const s = new Set([1,2,3,4,5]);
const it2 = s.values();
console.log([...it2])
// [1,2,3,4,5]
- for(...){}取值
// 跌代器取值3
const s = new Set([1,2,3,4,5]);
const it3 = s.values();
for(const val of it3){
console.log(val)
}
// 1,2,3,4,5
- Array.from(arrayLike,mapFn,thisArg) 取值
- arrayLike:伪数组对象或者可迭代的对象
- mapFn:可选,如果有,新数组中的每个元素都会执行此回调函数
- thisArg:可选,回调函数的this指向对象
//迭代器取值4
const s = new Set([1,2,3,4,5]);
const it4 = s.values();
const arr = Array.from(Array(5),it4.next,it4).map(x => x.value)
console.log(arr)
// [1,2,3,4,5]
- 生成器构造无穷斐波那契数列
// 求前10项
function* fibonaqi(){
let a = 1, b = 1;
yield a;
yield b;
while(true){
const t = b // 存储 第一位
b = a + b; // 第三项等于前两项的值相加
a = t; // 赋值第一位
yield b; // 执行一次
}
}
const it = fibonaqi();
const feb10 = Array.from(Array(10), it.next, it).map(x => x.value)
console.log(feb10);
// [1,1,2,3,5,8,13,21,34,55]
- 数组的展平
function* flatten(arr){
for(let i = 0; i < arr.length; i++){
if(Array.isArray(arr[i])){
yield *flatten(arr[i])
}else{
yield arr[i]
}
}
}
console.log(flatten([1,2,[3,4,[5]]]))
// flatten{<suspended>}
// 必须用展开符[...flatten()]
console.log([...flatten([1,2,[3,4,[5]]])])
// [1,2,3,4,5]
- generator 异步语法 // 需要TODO
function request(url){
return cb => {
setTimeout(() => {
cb(Math.random())
}, 1000)
}
}
// 自调用此函数收到一个函数,并执行返回的函数
create_runner(function*(){
const val1 = yield request('some url');
const val2 = yield request('some url');
console.log(val1, val2)
})();
// 传入一个函数返回一个经过处理的函数,
function create_runner(genFunc){
const it = genFunc(); // 迭代器
// data 是谁? cb吗?
function run(data){
const itVal = it.next(data);
if(!itVal.done){
itVal.value(run)
}
}
return run
}
- 迪卡尔积
- [1,2]*['a','b'] = [[1,'a'],[1,'b'],[2,'a'],[2,['b']]]
function cartesian_product(...Matrix){ if(Matrix.length === 0){ return []; } if (Matrix.length === 1){ return Matrix[0]; } console.log('Matrix',Matrix); return Matrix.reduce((A, B) => { console.log('a',A) console.log('B',B) const product = []; for(let i = 0; i < A.length; i++) { for(let j = 0; j < B.length; j++){ product.push( Array.isArray(A[i]) ?[...A[i],B[j]] :[A[i],B[j]] ) } } return product; }) } let a = cartesian_product(['a','b'],[1,2]) // //0: (2) ["a", 1] //1: (2) ["a", 2] //2: (2) ["b", 1] //3: (2) ["b", 2] - 链式操作
- ..map().filter().sort().map()
- 优点: 语义清晰、思考方便
- 缺点: 性能、空间
- 场景: 数据返回数组。小于1万。
四、常用算法
- 递归 就是自己调用自己
//阶乘
function factorial(n){
return n === 0 ? 1 :factorial(n-1) * n
}
let fa4 = factorial(4);
//1*2*3*4 24
// 斐波那契数列
funcition fibonacci(n){
let [a,b] = [0,1];
for(let i = 0; i < n; i ++){
[a,b] = [b,a+b]
}
return b;
}
// fibonacci(5) //8
function fibonacci(n){
return Array(n).fill().reduce(([a,b],_) => {
return [b, a+b]
}, [0,1])[1]
}
let a = fibonacci(5);//8
//fill 通过序数拿值
Array(10).fill(0).map((x,i)=>i)
//[0,1,2,3,4,5,6,7,8,9]
Array.from({length: 10},(_, i) => i)
// [0,1,2,3,4,5,6,7,8,9]
//
[...Array(10)].map(_,i)=>i);
//[0,1,2,3,4,5,6,7,8,9]
//深度拷贝对象
function clone(obj){
if(obj ==null || typeof obj !== 'object'){
return obj
}
const newObj = new obj.constructor();
for(let key in Object.getOwnpropertyDescriptors(obj)){
newObj[key] = clone(obj[key])
}
return newObj;
}
//深度比较
function deepCompare(a,b){
if(a === null || typeof a !== 'object' || b ===null || typeof b !=="object"){
return a === b;
}
const propsA = Object.getOwnPropertyDescriptors(a);
const propsB = Object.getOwnPropertyDescriptors(b);
if(Object.keys(propsA).length !== Object.keys(propsB).length){
return false;
}
return Object.keys(propsA).every(key => deepCompare(a[key],b[key]))
}
//树
- 实现findFibonacci函数
// 斐波那契数列段:从第三位起,每个数字都是前两位数字之和,不一定要从 1 开始
// 入参格式参考:
const inputArr = [13, 9, 3, 8, 5, 25, 31, 11, 21];
/* 实现findFibonacci函数,在一堆正整数中,找到最长的一组斐波那契数列段*/
function findFibonacci(arr) {
//todo
}
console.log(findFibonacci(inputArr)) // should print [3, 5, 8, 13, 21]
- 深度优先搜索
// 实现一个深度优先搜索算法(非递归)
function dfs(tree, name){
// 请在这里实现
}
var tree = {
name : '中国',
children : [
{
name : '北京',
children : [
{
name : '朝阳群众'
},
{
name : '海淀区'
},
{
name : '昌平区'
}
]
},
{
name : '浙江省',
children : [
{
name : '杭州市',
code : 0571,
},
{
name : '嘉兴市'
},
{
name : '绍兴市'
},
{
name : '宁波市'
}
]
}
]
};
var node = dfs(tree, '杭州市');
console.log(node); // { name: '杭州市', code: 0571 }
- 大整数相加运算
// 请通过代码实现大整数(可能比Number.MAX_VALUE大)相加运算
var BigInt = function (str) {
// your code here
};
BigInt.prototype.plus = function (bigint) {
// your code here
return this.toString(result);
};
BigInt.prototype.toString = function (result) {
// your code here
};
var bigint1 = new BigInt('1234232453525454546445451434342153453454545454545454');
var bigint2 = new BigInt('1234232453525454546445451434342153453454545454545454');
console.log(bigint1.plus(bigint2));