文章目录
一、 值传递与引用传递
- 1.值传递:只在基本类型之间存在,数值,字符串
// 1.赋值
let a = 1;
let b = a;
// 值传递,只在基本类型之间存在,数值,字符串,布尔值等等
console.log("a=%d ,b=%d", a, b); //a=1,b=1
// 更新a
a = 2;
console.log("a=%d ,b=%d", a, b); //a=2,b=1
- 2.引用传递,适用于引用类型,对象,数组
let obj1 = {
// 身份证号: 123, //身份证号: 123 和 姓名: '张三',这两个整体叫对象
// 姓名: '张三' //身份证号和姓名是 键 ,123和张三是 值
a: 1,
b: 2,
};
console.log("obj1 = %o", obj1); //obj1 = {a: 1,b: 2}
let obj2 = obj1;
console.log("obj2 = %o", obj2); //obj2 = {a: 1,b: 2}
console.log(obj1 === obj2); //ture
// 更新obj1
// 对象使用点 . 语法来访问内部成员
obj1.a = 10;
console.log("obj1=%o", obj1); //obj1 = {a: 10,b: 2}
console.log("obj2=%o", obj2); //obj2 = {a: 10,b: 2}
2.我们这种引用传递的时候并没有创建一个新的变量,只是给当前的变量创建了一个别名,从而去引用(当做去引用)
- 3.传参:永远是值传递
const f1 = function (x) {
x = 10;
};
//下面是箭头函数形式
// const f1 = (x) => (x = 10);
let m = 5;
f1(m);
// m:入参,调用函数时往里传的参数叫入参
//当前传入的是一个基本类型,原始类型,整数
console.log("m=%d", m); //m=5
//当传入的参数是一个对象时
const f2 = (x) => (x.a = 10);
let o = { a: 1, b: 2 };
f2(o);
console.log("0.a=", o.a); //0.a= 10
//当x为空时
const f3 = (x) => (x = {});
let p = { a: 1, b: 2 };
f3(o);
console.log("0.a=", o.a); //0.a= 1
概念
//深拷贝:值传递 (直接把值给你了)
//浅拷贝:引用传递 (把一个数据的地址给你,值没有发生变化)
二、模板字面量与标签函数
- 1.模板字面量
let name = "朱老师";
// let str = "Hello" + name;
// console.log(str); //Hello 朱老师
let str = `Hello ${name}`; //定界符:${}
// 字面量:Hello
// 插值:${ name }
console.log(str);
// 1.模板字面量:将表达式/插值嵌入到字符串
// 0 1 2
let menus = ["首页", "视频", "文章"];
let htmlStr = `
<nav>
<a href="">${menus[0]}</a>
<a href="">${menus[1]}</a>
<a href="">${menus[2]}</a>
</nav>
`;
// 写在``标签内的代码在页面上的显示会跟着代码自动换行
console.log(htmlStr);
document.body.insertAdjacentHTML("beforeEnd", htmlstr); //这行代码可以将 console.log(htmlStr); 显示在页面上,而不是只在后端显示
模板字面量内部由两部分组成:字符串字面量,变量插值
字符串字面量 | 变量插值 |
---|---|
<nav> <a href=""> </a> </nav> | ${....} |
- 2.标签函数,自定义模板字面量的一些行为
// let hello = (name) => alert(name);
// hello("天蓬老师");
// hello`天蓬老师`;
// 参数约定
// 1.第一个参数:所有字符串字面量组成的数组
// 2.第二个参数:插值组成的数组
let sum = (strs, a, b) => {
console.log(strs);
console.log(a, b);
};
let a = 45;
b = 28;
sum`${a} + ${b} = `; //[45,28]
// rest:归并函数
sum = (strs, ...args) => {
console.log(strs);
console.log(args);
};
let c = 38;
sum`${a} + ${b} + ${c} = `; //[45,28,38]
三、解构赋值
等于号 “=” 右边是被解构的对象,左边是解构后的新变量,这新变量可以重新赋值或者设置默认值
// let arr = [1, 2, 3];
//下面将数组解构成三个变量
// let a = arr[0];
// let b = arr[1];
// let c = arr[2];
// console.log(a, b, c); //1,2,3
- 1.数组解构
// 数组解构
// 等号左边是右边的模板,必须长得一样,右边的是原对象,也就是被解构的对象。
// let [a, b, c] = [1, 2, 3];
// console.log(a, b, c); //1,2,3
//左边是解构后的新变量,这新变量可以重新赋值或者设置默认值
// [a, b, c = "js"] = [1, 2];
// console.log(a, b, c); //1,2,js
// [a, b, ...c] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// console.log(a, b, ...c);
// [, , , a, , ] = [1, 2, 3, 4, 5, 6]; //拿取指定的值
// console.log(a);
数组解构的简单应用案例
//把x和y的值交换过来,需要创建一个中间变量,比较麻烦
let x = 1,
y = 2,
t;
console.log(x, y); //1,2
t = x;
x = y;
y = t;
console.log(x, y); //2,1
//用数组解构的方法
let a = 10;
b = 20;
console.log("a=%d,b=%d", a, b); //a=10,b=20
[b, a] = [a, b];
console.log("a=%d,b=%d", a, b); //a=20,b=10
- 2.对象解构
// 等号左边是右边的模板,必须长得一样
let item = { id: 10, name: "手机" };
let id = item.id;
let name = item.name;
console.log("id=%d,name=%s", id, name); //id=10,name=手机
// ({ id, name } = { id: 10, name: "手机" });
({ id, name } = { id: 40, name: "电脑" });
console.log("id=%d,name=%s", id, name); //id=40,name=电脑
- 3.参数解构
// 数组传参
// 模板 对象
let sum = ([a, b]) => a + b;
console.log(sum([30, 50]));
// 对象传参
let getUser = ({ name, email }) => [name, email];
console.log(getUser({ name: "朱老师", email: "admin@php.cn" }));
== 注意查看解构格式 ==
四、对象字面量的简化
简化的前提:
1.同一个作用域(都在全局,也就是同一个代码文件里)
2.变量与属性同名
// grtinfo是方法
let user = {
userName: "天蓬老师",
userEmail: "tp@qq.com",
getInfo: function () {
return `${this.userName} : ${this.userEmail}`; //用this关键字进行引用
},
};
console.log(user); //{userName: "天蓬老师", userEmail: "tp@qq.com", getInfo: f}
//对象结构
let { userName, userEmail } = user;
console.log(userName, userEmail); //天蓬老师 tp@qq.com
// 进行简化
// 对象字面量中的属性值引用的变量,如果与对象在同一个作用域中,则
// 并且这个变量与对象的属性同名,则可以省去不写
user = {
userName: userName,
userEmail: userEmail,
getInfo: function () {
return `${this.userName} ${this.userEmail}`;
},
};
console.log(userName, userEmail); //天蓬老师 tp@qq.com
//再次简化
// 对象字面量中的属性值引用的变量,如果与对象在同一个作用域中,则可以省去属性值
// 并且这个变量与对象的属性同名,则可以省去不写了
user = {
userName,
userEmail,
getInfo: function () {
return `${this.userName} ${this.userEmail}`;
},
};
console.log(userName, userEmail); //天蓬老师 tp@qq.com
//简化的前提
//1.同一个作用域
//2.变量与属性同名
五、三个关键字:bind(),call(),apply()
- this:就是 代码 执行上下文,程序运行 的一个运行环境
- this当前是window,全局
先给个例子,下面三个关键字的教学都引用到这个例子里面的值
//先给个例子,下面三个关键字的教学都引用到这个例子里面的值
function hello(name) {
// this:就是 代码 执行上下文,程序运行 的一个运行环境
// this当前是window,全局
this.name = name;
// window.name=name
console.log(this); //name: "朱老师"
}
hello("朱老师");
- 1.bind(可以改变函数的this指向)
// bind(可以改变函数的this指向)
const obj = {
name: "天蓬老师",
};
// bind()只绑定不执行
let f = hello.bind(obj, "admin");
console.log(f()) //name: "admin"
- 2.call或apply(如果函数中的this被重新绑定之后,要求立即执行就,就用call或apply)
// 如果函数中的this被重新绑定之后,要求立即执行
// 用call或apply
// f = hello.call(obj, "灭绝老师"); 可以不需要 f
hello.call(obj, "灭绝老师"); //直接作用于上面的 console.log(f()) 不用再次打印
//如果有多个参数就要使用数组
hello.apply(obj, ["西门老师", "欧阳老师"]);
- bind()案例
document.querySelector("button").addEventListener(
"click",
function () {
// this原来是绑定到按钮上的,bind()改变了this的指向
console.log(this.name);
console.log(this);
}.bind({
name: "朱老师",
})
);
- 总结
关键字 | 相同点 | 不同点 |
---|---|---|
bind() | 都可以改变this的指向 | 只绑定,不执行 |
call() | 都可以改变this的指向 | 绑定后立即执行,但参数不一样;参数是离散的一个一个传入 |
apply() | 都可以改变this的指向 | 绑定后立即执行,但参数不一样;参数以数组的形式统一传入 |
六、访问器的属性
- 1.访问器属性:将一个方法伪装/包装成一个属性
// 对象成员:属性,方法
// 属性:类似于变量
// 方法:类似于函数
const product = {
data: [
{ id: 1, name: "电脑", price: 5000, num: 5 },
{ id: 2, name: "手机", price: 4000, num: 15 },
{ id: 3, name: "相机", price: 14000, num: 10 },
],
// 计算总金额
// 方法也就是函数 getAmounts()
// es6的方法的简化,将冒号和function可以删除
//下面用数组函数演示,暂时还没学,看案例效果,先不要纠结看不懂这个函数
getAmounts: function () {
return this.data.reduce((t, c) => (t += c.price * c.num), 0);
}, //总金额 = 99000
// 访问器属性:将一个方法伪装/包装成一个属性
// get:是读取,也叫读操作
get total() {
return this.data.reduce((t, c) => (t += c.price * c.num), 0);
}, //总金额 = 99000
// set: 访问器属性的写操作
set setPrice(price) {
this.data[1].price = price;
},
};
console.log("总金额 = %d元 ", product.getAmounts());
//不想用方法,想以属性的方式来获取总金额
console.log("总金额 = %d元 ", product.total);
console.log(product.data[1].price); //金额修改前
product.setPrice = 8000; //这是一个属性,属性可以直接赋值
console.log(product.data[1].price); //金额修改后
- 2.访问器属性的优先级(拓展):访问器属性的优先级高于同名的普通属性
let user = {
data: { name }, //同名的普通属性
get name() {
return this.data.name;
},
set name(v) {
return (this.data.name = v); //访问器属性
},
};
user.name = "天蓬老师"
console.log(user.name); //现在访问的是set赋值的name,压根没有访问 data: { name }
// 访问器属性的优先级高于同名的普通属性
七、流程控制—分支
- 1.单分支:只有一种情况
let score = 70;
// 单分支:只有一种情况
if (score >= 60) //如果 scored 的值大于60,则显示及格,小于则不显示
console.log("及格"); //及格
- 2.双分支:两种情况
// 2.双分支:两种情况
// else:默认分支,意思就是当别的条件不满足的时候就默认执行else分支
if (score >= 60) console.log("及格");
else console.log("补考"); //及格
- 3.多分支:多种情况
&:并且,该符号两边的情况需要同时满足; ||:或者,该符号两边的情况只需要满足一种即可
// 3.多分支:多种情况
// &:并且,该符号两边的情况需要同时满足; ||:或者,该符号两边的情况只需要满足一种即可
score = 123;
if (score >= 60 && score < 80) {
console.log("及格");
} else if (score > 100 || score < 0) {
console.log("非法数据");
} else if (score >= 80 && score <= 100) {
console.log("学霸");
} else {
console.log("补考");
} //非法数据
- 4.多分支简化
多分支简化 用switch (),括号中给 ture 才能使 switch 进入到分支中
switch 很少用于多值判断,通常用于单值判断
- switch 的多值判断用法
// 多分支简化 用switch (),括号中给 ture 才能使 switch 进入到分支中
// switch 很少用于多值判断,通常用于单值判断
// switch 的多值判断用法
score = 10;
// 括号为开启或关闭
switch (true) {
case score >= 60 && score <= 80:
console.log("及格");
break; //跳出
case score >= 0 && score <= 60:
console.log("补考");
break;
case score > 100 || score < 0:
console.log("非法数据");
break;
// case score >= 80 && score <= 100:
// console.log("学霸");
// break;
default:
console.log("学霸");
}
- switch 的单值判断用法
// switch 的单值判断用法
let status = "SuCcess"; //一般区分大小写,下面用 toLowerCase() 可以把 status = "" 里面赋的值全部转换成小写
switch (status.toLowerCase()) {
case "success":
console.log("成功");
break;
case "error":
console.log("失败");
}
- 三元运算符:专用于简单化双分支结构的语法
score = 89;
if (score >= 60) console.log("及格");
else console.log("补考");
// (简化语法)三元运算符:专用于简单化双分支结构的语法
// true位置:判断为真时返回的值 false位置:判断为假的时返回的值
// console.log(score >= 60 ? true : false);
console.log(score >= 60 ? "及格" : "补考"); //及格