值传递与引用传递的区别
1.1 值传递: 原始类型,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);
1.2 引用传递: 引用类型,对象object,数组array
let obj1 = { a: 1, b: 2 };
let obj2 = obj1;
// 更新obj1
obj1.a = 10;
// 此时obj1就会更新为10
console.log(obj1);
// obj2同步更新
console.log(obj2);
// 这是可以将obj2理解为obj1的一个别名
- 传参
传参时,不论什么类型,都是”值传递”
入参: 调用函数是传入的参数,简称:”入参”
函数中对参数的更新,并不会影响到入参
实参:函数内为实参
引用传递
函数中对于对象参数/引用参数的更新并没有影响到入参
数组和对象解构的常用方法
解构赋值: 快速从集合数据(数组/对象)解构出独立变量
- 数组
也可以解构其中只两个数组let [a, b, c] = [1, 2, 3];
将数组中的123解构的左边的abc的三个变量中
如果左边的变量比右边的数组多可以给多出来的变量一个默认值[a, b] = [1, 2, 3];
如果数组中有很多值可以将多个值压入一个变量中[a, b, c, d = "xxxx"] = [1, 2, 3];
如果只想取其中一个值可以用以下方法[a, b, ...c] = [1, 2, 3, 4, 5];
[, , a, ,] = [1, 2, 3, 4, 5];
数组的解构应用场景
将数组中的值进行调换
原始代码:
let x = 1,
y = 2,
t;
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];
- 对象解构
属性名与变量名必须一一对应,顺序无所谓
当变量重名是可使用()将解构语句包起来进行重新赋值let { id, name } = { id: 10, name: "手机" };
console.log(id, name);
// 属性名与变量名必须一一对应,顺序无所谓
({ name, id } = { id: 10, name: "手机" });
console.log(id, name);
为防止变量重名可以对变量设置别名
let email = "admin@php.cn";
//为email添加: userEmail 别名 email: userEmail
let { role, email: userEmail } = { role: "user", email: "user@php.cn" };
//调用时直接调用别名即可不会影响变量email 的值
console.log(userEmail);
3.参数解构
数组传参
let sum = ([a, b]) => a + b;
//[10, 20]数组传参解构
console.log(sum([10, 20]));
对象传参
let getUser = ({ name, email }) => [name, email];
//对象的解构
console.log(getUser({ email: "tp@php.cn", name: "天蓬老师" }));
call,apply,bind的区别
bind()函数
bind()方法主要就是将函数绑定到某个对象
bind()不会立即执行,只返回一个函数声明
bind()应用案例: 动态改变this
document.querySelector("button").addEventListener("click",function () {
}.bind({ name: "猫科动物" })
);
call,apply为立即执行
function hello(name) {
this.name = name;
console.log(this.name);
}
const obj = {
name: "admin",
};
// call/apply立即执行
f = hello.call(obj, "你好");
console.log(f);
f = hello.apply(obj, ["老师"]);
console.log(f);
访问器属性的原理
原始调用方法
原始调用方法
const product = {
data: [
{ name: "电脑", price: 5000, num: 5 },
{ name: "手机", price: 4000, num: 10 },
{ name: "相机", price: 8000, num: 3 },
],
getAmounts() {
return this.data.reduce((t, c) => (t += c.price * c.num), 0);
},
}
//方法调用
console.log("总金额 :", product.getAmounts());
访问器属性访问方法
const product = {
data: [
{ name: "电脑", price: 5000, num: 5 },
{ name: "手机", price: 4000, num: 10 },
{ name: "相机", price: 8000, num: 3 },
],
// 访问器属性
// 将方法伪造成一个属性
get total() {
return this.data.reduce((t, c) => (t += c.price * c.num), 0);
},
};
//用访问器属性调用
console.log("总金额 :", product.total);
访问器属性的优先级
let user ={
// 普通属性
name:'nihao',
// 访问器属性
get name(){
return '1111';
}
}
// 此时访问器属性比普通属性优先级高
console.log(user.name);
注:在同一个对象中不能用重名的属性
解决方法:
let user = {
data: { name },
get name() {
return this.data.name;
},
set name(value) {
this.data.name = value;
},
};
user.name = "user.name";
console.log(user.name);
流程控制-分支
单分支
let score = 54;
// 单分支
if (score >= 60) {
console.log("及格");
}
双分支
if (score >= 60) {
console.log("及格");
// else默认分支
} else {
console.log("补考");
}
多分支
score = 98;
if (score >= 60 && score < 80) {
console.log("合格");
} else if (score >= 80 && score <= 100) {
console.log("学霸");
}else if (score > 100 || score < 0) {
console.log("非法数据");
} else {
console.log("补考");
}
switch来简化多分支 switch是严格匹配
score = 198;
switch (true) {
case score >= 60 && score < 80:
console.log("合格");
break;
case score >= 80 && score <= 100:
console.log("学霸");
break;
// 判断成绩是否合法
case score > 100 || score < 0:
console.log("非法数据");
break;
default:
console.log("补考");
}
switch一般用在单值判断
let response = "Success";
switch (response.toLowerCase()) {
case "fail":
console.log("请求失败");
break;
case "success":
console.log("请求成功");
break;
default:
console.log("未知错误");
}
三元运算符
条件? true : false
用于简写双分支
原始双分支:
if (score >= 60) {
console.log("及格");
// 默认分支
} else {
console.log("补考");
}
三元运算符简写
score = 80;
console.log(score >= 60 ? "及格" : "补考");