1.
var a =3;
a=a-3||a+4;
//就等于以下代码
if(a===3){
a+4}
else{ a-3}
2
var a;
a=a||3 //判断a 是不是“”,null,flase,0,undefind,null,
//若是就给a赋值给b,若a 是这六个则把3赋值给b
3.递归函数
function sum(arr, n) {
if(n<=0){
return 0;
}
return sum(arr,n-1)+arr[n-1]
}
console.log(sum([2, 3, 4,5], 3));
//写一个递归函数,sum(arr, n),返回递归调用数组 arr 从前 n 个元素和
注意: 递归函数在没有函数调用时(在这个例子是,是当 n <= 0
时)必需有一个跳出结构,否则永远不会执行完毕。
4.引用类型的赋值问题
4.1
var obj = { name: 'Jack' }
function fn(o) {
o.name = 'Rose'
var o = new Object() //o又给了一个新地址不在用全局obj,所以下面再改键值,obj的键值不变
o.name = 'Tom'
console.log('形参 o : ', o.name) // Tom
}
fn(obj)
console.log('全局 obj : ', obj.name) // Rose
var obj = { name: 'Jack' }
function fn() {
obj.name = 'Rose'
obj = new Object() //相当于给全局obj了一个新地址,此时新地址的value为空
obj.name = 'Tom'//给全局的obj设置name为Tom
console.log('函数内 obj : ', obj.name) // Tom
}
fn()
console.log('全局 obj : ', obj.name) //Tom
5.函数的防抖与节流
5.1防抖
事件被触发时,在n秒后执行函数,在n秒内多次触发事件,则重新开始计时
例如:在输入框的输入事件中,为了防止每次输入都会调用函数,设置防抖会在你输入第二次的时候把第一次的关了开启第二次,输入第三次的时候把第二次干了打开第三次........
示例:
var timer=0 //设置一个与定时器一样的变量
inp.oninput = function () {
var timer=setTimeout(()=>{
clearInterval(timer)//在第二次的时候就会把第一次的关了
.....
},300) }
用法:刚开始设置一个跟定时器相同名字的变量,在开启定时器的第一句就关闭定时器,这样因为你全局定义了跟定时器名字一样的变量,在第一次执行,从上往下,会先执行 clearInterval(0),不会第一次不执行,到了你第二次点的时候就会先执行 clearInterval(timer),会把第一次的停掉一次执行
5.2节流
在规定的单位时间段内,函数只能执行一次,在单位时间内多少触发,则只有一次有效
通过开关实现,先定义一个flag=true ,在事件正在运行的时候让他变成false,事件完成后在变成true
示例:
let flg=true;//开始定义一个开关
div.onclick=function(){
if(!flg)return
flg=false //关闭开关
let diance=0
const timer=setInterval(function(){
diance +=100
div.style.left=diance+'px'
},300) //等完成的时候flg=true
区别:节流是在函数还没执行完的时候,再触发事件的时候把事件停掉,让事件无法触发,等一个事件处理完成后,再打开开关,继续下一个
防抖是,在你第二次事件触发的时候把第一次停掉,在第一次事件触发的时候你可以触发第二次事件,
两个的触发的时间点不一样,例如一个定时器3s,节流是在3秒后你才能触发事件,防抖是你在0-3秒之内都可以触发事件,但是会把上一次事件给结束掉
6.数组解构问题
var arr1=[4,5,6]
var[a,b]=arr1
console.log(typeof b);
function fn(...arr){
var [layer,...d]=arr; // 问题:执行到最后b是一个数组[5],...b是5,在数组解构的时候...后跟的永远是数组类型
return d.length ? Array(layer).fill(0).map(_=>fn(...d)) : Array(layer);
}
console.log(fn(2,3,4,5));
正则题
var str = "Hellllo world";
str = str.replace(/(l)\1/g, '$1'); //输出hello word
对于正则表达式 /(l)\1/g,其中(l)是第一个分组,\1指向第一个分组,即\1重复了第一个分组的内容,所以该正则表达式可以表示成/(ll)/g
而对于第二个参数$1,表示用第一个分组的内容 l 对匹配到的部分进行替换(即 ll 替换成 l ),同时正则表达式有g表示全局匹配,所以4个ll被替换成2个ll
类型转换
console.log(([])?true:false); //true
console.log(([]==false?true:false)); //true
console.log(({}==false)?true:false) //flase
第二题,和第三题
布尔类型与其它任何类型进行比较,布尔类型将会转换为number类型。
Number([])返回0所以第二题为true
Number转换类型的参数如果为对象返回的就是NaN,
那么Number({})返回的就是NaN。
对象
1.在对象中有中括号[],
在使用[]后,会优先判断是不是字符类型,如果不是字符类型就判断是不是Symbol
// 如果也不是Symbol,就会把这个类型隐式转换为字符串
var o={};
var o1={a:1};
var o2={a:2};
var o3='5'
o[o1]=10;
//o1是对象类型,不是字符串也不是Symol()类型,所以转换成 "[object Object]"
console.log(o[o2]);//10
//o2也是同上,所以也是 "[object Object]",注意:在这里o1,o2是key
console.log(o[o3]) //undefinded //因为o3是字符串类型
var c=Symbol()
var o={
a:1,
b:2,
[c]:3
}
var d={a:1}
var e={b:1}
o[d]=3
console.log(o);
console.log(o[e]);//3
this指向
function wrap1(){
console.log(this);//wrap1
func=()=>{
console.log(this);//wrap1,因为再new的时候产生了一个新对象,
就是en1所以在构造函数内部的this指向wrap1,因此在箭头函数的this跳到上一层,就会是wrap1
}
func();
}
let en1=new wrap1();
function wrap(){
console.log(this);//这里的是wrap,跟上一个案例一样毫无疑问
function func(){
console.log(this);//win,这里并没用箭头函数,这里的this并不在构造函数直系内部,
而是在func函数内部,所以指向window,相当于解析成下面的对象
}
func();
}
let en=new wrap();
---------------------------------------------------------------------
var en={
fun:function(){
function func(){
console.log(this);//window
}
func()
}
}
obj.fun(