js递归方式1–100求和
// 递归
let add = function(num1,num2){
var num = num1+num2
if(num2+1>100){
return num
}else{
return add(num,num2+1)
}
}
add(1,2)
// 循环
let sun=0;
for(let a=0;a<=100;a++){
sun+=a
}
console.log(sun)
//
function sun(n) {
if (n === 1) return 1
return sun(n - 1) + n
}
sun(100)
数组去重
ES5
let arr = [1,2,321,1,1,3,1]
function fn(){
let arr1=[]
for(let a of arr){
if(arr1.indexOf(a) === -1){
arr1.push(a)
}
}
}
ES6
// 1.使用set方法
arr=[...new Set(arr)]
// 2.Array.from()能把set结构转换为数组
function dedupe(array) {
return Array.from(new Set(array));
}
节流防抖
- 防抖:在第一次触发事件的时候,不立即执行函数,而是给出一个期限值,比如200ms,然后在200ms内没有触发事件,那么就执行函数,如果触犯了,那么计时取消,重新开始计时
let fn=function(){
console.log(0)
}
// 防抖函数
let debounce = function(fn,delay){
let timer = null // 计时器
return function(){
if(timer){ // 如果有值,取消计时器,重新计时
clearTimeout(timer)
timer = setTimeout(fn, delay)
}else{ // 没有值开始计时
timer = setTimeout(fn, delay)
}
}
}
debounce(fn,1000)
- 节流:在规定的时间内,不断的触发事件,只会最后一次触发操作
let throttle = function(fn,delay){
let flag = true;
return function(){
if(flag){
return false
}
flag = false
setTimeout(()=>{
fn()//执行函数
flag = true
},delay)
}
}
大数相加
js number的取值范围是 -2^53 - 2^53
超过这个范围,会出现精度丢失的问题
let a ='3123123123111',b='1321312312311';
function sun(num1,num2){
let arr1 = num1.split(''),arr2 = num2.split('')
let len = Math.max(arr1.length,arr2.length)
let arr=[]
let temp;
let flag=false;
for(let a =0;a<len;a++){
let n1 = arr1.pop()
let n2 = arr2.pop()
n1 = n1 ? n1 : 0
n2 = n2 ? n2 : 0
if(flag){
// 有进位
temp = parseInt(n1)+parseInt(n2)+1
}else{
temp = parseInt(n1)+parseInt(n2)
}
console.log(temp)
// 判断是否有进位
if(parseInt(temp / 10) > 0){
arr.push(temp%10)
flag = true
}else{
arr.push(temp)
flag = false
}
// 判断最后一位是否有进位
if(a === len-1 && flag){
arr.push(1)
}
}
// 反转数组
return arr.reverse().join('')
}
console.log(sun(a,b))
闭包
-
有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数
函数的变量作用域是独立的、封闭的、外部变量是访问不了的 ,但是闭包有这个能力和权限
- 闭包作为一个函数存在另一个函数中
- 闭包可以访问到父级函数的变量,且该变量不会销毁
function person(){ var name = 'Timi'; function cat(){ console.log(name); } return cat; } var per = person();// per的值就是return后的结果,即cat函数 per();// Timi per()就相当于cat() per();// Timi 同上,而且变量name没有销毁,一直存在内存中,供函数cat调用 per();// Timi
-
闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。
var age = 18; function cat(){ age++; console.log(age);// cat函数内输出age,该作用域没有,则向外层寻找,结果找到了,输出[19]; } cat();//19 // 如果一直掉用,会一直想加 cat();//20 cat();//21 cat();//22 > 如果程序还有其他函数,也需要用到age的值,则会受到影响,而且全局变量还容易被人修改,比较不安全,这就是全局变量容易污染的原因,所以我们必须解决变量污染问题,那就是把变量封装到函数内,让它成为局部变量。 function person(){ var age = 18; function cat(){ age++; console.log(age); } return cat; } person();// 19 person();// 19 // 每次掉用该函数,重新进入该作用域,age就会重新赋值,所有cat的值一直是19 var per = person();//per相当于函数cat per();// 19 即cat() 这样每次调用不在经过age的初始值,这样就可以一直增加了 per();// 20 per();// 21
-
优点:
- 隐藏变量,不回被全局变量污染
- 可以读取函数内部的变量
缺点:
- 导致变量不会被垃圾机制回收,造成内存消耗
- 不恰当的使用闭包,造成内存消耗的问题
-
垃圾机制:JS规定在一个函数作用域内,程序执行完以后变量就会被销毁,这样可节省内存;
使用闭包的时候,按照作用域链的特点,闭包外面的函数不回被销毁,因为函数会一直掉用,所以会一直存在,如果闭包使用过多,会导致内存销毁
深拷贝&浅拷贝
浅拷贝
let a=[0,1,2,3,4],
b=a;
console.log(a===b); // true
a[0]=1;
console.log(a,b); // [1,1,2,3,4]
// 改变a的值,b也会随着改变
-
基本数据类型number,string,boolean,null,undefined五类
name val a 1 当b=a复制时,栈内存会新开辟一个内存,例如这样:
name Val a 1 b 1 - 现在修改b的时候,对a不会造成影响
- 当然let a=1,b=a;虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。
-
引用数据类型(Object类)有Object,Array,Date等。
引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值
当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值
- 而当我们修改a中的值的时候,由于a和b指向的是同一个地址,所以b也会收到影响,这就是浅拷贝
- 所以我们要在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,起步就达到深拷贝的效果了
- 实现深拷贝
let a=[1,2,3,4] b=JSON.parse(JSON.stringify(a))
function deepCopy(obj) { var newObj = obj.constructor === Array ? [] : {}; newObj.constructor = obj.constructor; if (typeof obj !== "object") { return; } else { for (var prop in obj) { console.log(prop) if (obj[prop].constructor === RegExp || obj[prop].constructor === Date) { newObj[prop] = obj[prop]; } else if (typeof obj[prop] === 'object') { //递归 newObj[prop] = deepCopy(obj[prop]); } else { newObj[prop] = obj[prop]; } } } return newObj; } let arr = [1,23,13,13,13,13,123] deepCopy(arr)
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。let a=[0,1,[2,3],4], b=$.extend(true,[],a); a[0]=1; a[2][0]=1; console.log(a,b);
事件委托
-
事件代理(Event Delegation),又称之为事件委托,是javascript中绑定事件的常用技巧,即吧原来需要绑定给自己的事件绑定给父元素,让父元素担任监听事件的职务,原理就是js的事件冒泡
-
-
事件冒泡:当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window
-
事件捕获:从window一直传递到自己本身
-