值传递与引用传递
- 值传递
-赋值
-值:原始类型,string,number,bool - 引用传递
-引用类型,object,array - 传参
-传参时,不论什么类型,都是“值传递”
-入参:调用函数是传入的参数
-函数中对参数的更新,并不会影响到入参
-对与引用类型,只有全新赋值才算是更新,修改属性不算的
-赋值一个全新的对象,才是更新
-函数中对于对象参数/引用参数的更新并没有影响到入参 - 深拷贝:值拷贝
- 浅拷贝:引用传递
<script>
//-值:原始类型,string,number,bool
let a= 1;
let b =a;
console.log("a = %d,b = %d",a ,b);
a = 2;
//更新a,不影响b
console.log("a = %d,b = %d",a, b);
//引用类型,object,array
let obj1 = {a:1,b:2};
console.log(obj1);
let obj2 = obj1;
console.log(obj2);//值不变
//更新obj1
obhj1.a = 10;
console.log(obj1);
// obj2同步更新
console.log(obj2);
//传参时,不论什么类型,都是“值传递”
const f1 = x =>(x=10);
let m = 5;
console.log("m = %d" , m);
f1(m);
// 入参:调用函数是传入的参数
console.log("m = %d" , m);
const f2 = x => (x.a = 10);
let o = {a:1,b:2};
console.log(0);
f2(o);
//看上去函数中对于o.a的更新生效,实际上仍是值传递
console.log(o);
//对与引用类型,只有全新赋值才算是更新,修改属性不算的
const obj = {x:1,y:2};
obj.x = 20;
//赋值一个全新的对象,才是更新
obj = {};
const f3 = x =>(x={});
f3(o);
console.log(o);
</script>
模板字面量/标签函数
- 模板字面量:将表达式嵌入到字符串
-模板字面里使用反引号:“ ` ”
-模板字面量的组成
-字符串字面里: “+,=”;
-变量或表达式:a,b,(a+b)
-模板字面量创建多行字符串可以保留格式
<script>
//模板字面量,把表达式嵌入到字符串
let a = 1;
let b =4;
let res = a + “+” + B + "=" +(a+b);
console.log(res);
//使用反引号可以简写
res = `${a}+${b} = ${a+b}`;
console.log(res);
//模板字面量创建多行字符串可以保留格式
let menu = ['首页’,'视频','文章'];
let hemlStr = `<ul>
<li><a href="">${menu[0]}</a></li>
<li><a href="">${menu[1]}</a></li>
<li><a href="">${menu[2]}</a></li>
</ul>`;
console.log(htmlStr);
document.body.inserAdjacentHTML("beforeEnd",htmlStr);
</script>
标签函数:自定模板字面里的行为
- 使用自定义函数来处理模板字面量,它的参数约定
-第一个参数:模板字面里中的字符串字面量组成的数据
-从第二个参数开始,将模板字面量中的变量一次传入
-rest 简化
<script>
let hello = name=> alert(name);
hello`你好`;
//使用自定义函数来处理模板字面量,它的参数约定
//第一个参数:模板字面里中的字符串字面量组成的数据
//从第二个参数开始,将模板字面量中的变量一次传入
let sum = (strs,a,b)=>{
console.log(strs;)
console.log(a,b);
};
//调用用数组包起来
sum(['+','=',''],a,b);
sum`${a}+${b}=`;
//rest 简化
sum(strs,...args)=>{
console.log(strs)
console.log(args);
};
sum`${a}+${b}=`;
</script>
解构赋值
- 解构赋值
-快速从集合数据(数组/对象)解构出独立变量
-参数解构
-数组传参
//数组
<script>
let [a,b,c] =[1,2,3];
console.log(a,b,c);
[a,b] = [1,2,3];
console.log(a,b);
[a,b,c,d="xxxx"] = [1,2,3];
console.log(a,b,c,d);
[a,b,...c] = [1,2,3,4,5];
console.log(a,b,c);
[,,a,,] = [1,2,3,4,5];
console.log(a);
let x = 1, y= 2;
console.log("x=%d,y = %d",x,y);
t=x;
x = y;
y=t;
console.log("x=%d,y=%d",x,y);
[y,x] = [x,y];
console.log("x=%d,y=%d",x,y);
</script>
<script>
let{id,name}={id:10,name:"手机"};
console.log(id,name);
//属性名与变量必须一一对应,顺序无所谓
({name,id}={id:10,name:"手机"});
console.log(id,name);
//别名
let email;
{role,email:userEmail}={role:"user,email:"120@qq.com"}
console.log(userEmail);
//参数解构:数组传参
let sum = ([a,b]) => a+b;
console.log(sum([10,20]));
//对象传参
let getUser = ({name,email}) => [name,email];
console.log(getUser({name:"lisi",email:'510@qq.com'}));
</script>
对象自变量的简化
- 对象自变量简化
-当属性名与同一个作用域的变量名相同时,可以直接使用属性名来引用变量值
-方法也能简化:删除冒号和function,关键字 - 箭头函数:
- 箭头函数中的this总是指向定义它时的作用域(静态作用域/词法作用域),而并非调用时
-user 对象不能出创建作用域,this指向了user的作用域/作用域链
-全局没有userName,userEmail,所以输出 undefiend
<script>
let user = {
userName:"李四";
userEmail:"2000@qq.com";
getInfo:function(){
retrun `${this.userName}(${this.userEmail})`;
},
};
console.log(user,getInfo());
let {userName,userEmail} = user;
console.log(userName,userEmail);
let user = {
//当属性名与同一个作用域的变量名相同时,可以直接使用属性名来引用
userName,
userEmail,
getInfo(){
retrun `${this.userName}(${this.userEmail})`;
},
};
//使用箭头函数
user = {
userName,
userEmail,
//使用箭头函数
getInfo:()=>`${this.userName}(${this.userEmail})`;
//当前函数中的this指向了全局window
test:()=>console.log(this),
}
console.log('简化:',user,getInfo());
console.log(user.test());
</script>
bind,call,apply
- bind 不会立即执行
-动态改变this - call/apply 立即执行
- apply 必须是数组
<button>点击</button>
<script>
function hello(name){
this.name = name;
console.log(this.name);
}
const obj = {name:'admin',};
//经典调用
console.log(hellog("朱老师"));
//bind()不会立即执行,只返回一个函数声明
let f = hello.bind(obj,'你好');
console.log(f());
//call/apply立即执行
f= hello.call (obj,'世界');
console.log(f);
f= hello.apply(obj,['世界']);
console.log(f);
//bind()应用案例
document.querSelector('button').addEventListener('click',function(){
console.log(this.name);
console.log(this);
document.body.appendChild(document.createElement('p').innerHTML = '欢迎:' + this.name);
},bind({name:'猫科动物'}));
</script>
访问器属性
- 访问器属性
-将方法伪造成一个属性
-访问器属性优先级高于同名的普通属性
<script>
const product = {
data:[
{name:"电脑",price:5000,num:5},
{name:"手机",price:5000,num:5},
{name:"相机",price:5000,num:5},
],
getAmounts(){
return this.data.reduce((t,c)=>(t+=c.price*c.num),0);
},
//访问器属性
get total(){
return this.data.reduce((t,c)=>(t+=c.price*c.num),0);
},
set setPrice(price){
this.data[1].price = price;
}
}
console.log('总金额:',product.getAmounts());
console.log(总金额:',product.total);
product.setPrice=9988;
console.log(product.data[1].price);
</script>
流程控制-分支
- 流程控制
-if(){}else{}
-switch(){case “条件” break;default} - 三元运算符
-条件?true : false
<script>
let score = 64;
//单分支
if(score >= 60){
console.log('及格');
}
//双分支
if(score>=60){
console.log('及格');
} else {
console.log('补考');
}
//多分枝
if(score >= 60 && score <80){
console.log('合格');
}else if(score >= 80 && score <= 100){
console.log('学霸');
}
//判断成绩是否合法
else if (scoure > 100 || score < 0){
console.log('非法数据');
}
else {
console.log('补考');
}
switch(true){
case score >= 60 && scoure < 80:
console.log('合格');
break;
case score >= 80 && scoure < 100:
console.log('学霸');
break;
case score >100 || scoure < 0:
console.log('非法数据');
break;
default:
console.log('补考');
}
//switch用在单值判断
let respponse = 'Success';
switch(respponse.toLowerCase()){
case 'fail';
console.log('请求失败');
break;
case 'success';
console.log('请求成功');
break;
default:
console.log('未知错误');
}
// 三元运算符
console.log(score>=60 ?"及格" : "补考");
if(score>=10){
console.log('及格');
}else{
console.log('补考');
}
</script>