值类型与引用类型有什么区别?
哪些类型是值类型?哪些类型是引用类型
· 值类型:String、Number、Boolean、Symbol
· 引用类型:JSON、Array、null
演示值类型与引用类型的堆栈模型
变种提问
const a={x:100, y:200}
const b=a
let c=a.x
b.x=300
console.log(a) // x:300
演示代码
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@说人话的前端 - bilibili</title>
</head>
<body></body>
<script>
// 因为这时候的a1值为100:number值,所以更改b1的值互不影响
let a1 = 100;
let b1 = a1;
b1 = 200;
console.log(a1); // a1 = 100
// 而这时的a2是引用类型,他们共用一个引用值,所以当b2值变化的时候,a2也同时发生变化
let a2 = { age: 18 };
let b2 = a2;
b2.age = 20;
console.log(a2); // { age: 20 }
// 变种提问
// const a={x:100, y:200}
// const b=a
// let c=a.x // 这一行是误导的,忽略即可
// b.x=300
// console.log(a) // x:300
</script>
</html>
手写深拷贝
如何实现深拷贝
-
JSON.parse(JSON.stringify(obj))
不能存放函数、时间对象、正则...
-
递归
没有考虑循环引用。。
-
lodash.cloneDeep 推荐,工作中没必要重复造轮子
演示代码
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@说人话的前端 - bilibili</title>
</head>
<body></body>
<script>
const obj1 = {
name: "张三",
age: 18,
address: {
city: "北京",
},
hobby: ["台球", "篮球"],
fn: function () {
console.log(123);
},
};
const obj2 = deepClone(obj1);
obj2.age = 20;
obj2.address.city = "上海";
console.log(obj1);
console.log(obj2);
// 此方法仅适用简单的深拷贝,因为该方法会把拷贝中的函数、正则、时间对象、错误对象等都干没了
// function deepClone(obj) {
// return JSON.parse(JSON.stringify(obj));
// }
function deepClone(obj) {
// 判断该类型是不是一个对象或这个obj是不是空的如果不是就没必要去递归,直接返回出来就可以了
if (typeof obj !== "object" || obj == null) {
return obj;
}
// 判断一下这个obj是数组还是对象,然后让这个res等于数组/对象
let res = obj instanceof Array ? [] : {};
// 遍历obj
for (let key in obj) {
// 为了让代码更健壮
if (obj.hasOwnProperty(key)) {
// 再引用一次deepClone是为了解决有多层引用关系的情况
// name/age... "张三"/18... name:"张三"/age:18...
res[key] = deepClone(obj[key]);
}
}
return res;
}
</script>
</html>
何时使用==何时使用===
== 隐式类型转换
0 == ''
0 == false
false == ''
null == undefined
只有 obj == null 使用双等
if (obj === null || obj === undefined) {
}
演示代码
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@说人话的前端 - bilibili</title>
</head>
<body></body>
<script>
console.log(100 == "100");
console.log(0 == "");
console.log(0 == false);
console.log("" == false);
console.log(null == undefined);
let obj = { age: 18 };
if (obj == null) {
}
if (obj === null || obj === undefined) {
}
</script>
</html>
哪些是truly变量?哪些是falsely变量?
什么是truly变量?什么是falsely变量?
- truly变量:!!val === true
- falsely变量:!!val === false
除了falsely变量,都是truly变量
-
数字0
-
NaN
-
空字符串
-
null
-
undefined
演示代码
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@说人话的前端 - bilibili</title>
</head>
<body></body>
<script>
// ==会涉及到隐式类型转换
console.log(!!"" === false);
console.log(!!NaN === false);
console.log(!!0 === false);
console.log(!!null === false);
console.log(!!undefined === false);
// 只有 obj == null 使用双等,其他时候最好用全等===
if (obj == null){
}
if (obj === null || obj === undefined) {
}
</script>
</html>
哪些是truly变量?哪些是falsely变量?
什么是truly变量?什么是falsely变量?
- truly变量:!!val === true
- falsely变量:!!val === false
除了falsely变量,都是truly变量
-
数字0
-
NaN
-
空字符串
-
null
-
undefined
演示代码
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// !!:两次取反
console.log(!!"" === false);
console.log(!!NaN === false);
console.log(!!0 === false);
console.log(!!null === false);
console.log(!!undefined === false);
</script>
</body>
</html>
说说原型和原型链是怎么回事
复习class基础语法
- class
- construct
- extends
- super
- instanceof
什么是原型
什么是原型链
演示代码
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 父级
// class:声明一个类 Person:类的名字,可以自定义,但是首字母最好大写
class Person {
// constructor:构造函数,声明类的时候必须要有
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
// 这里括号的内容是用小点``包裹的,而不是用引号""
// console.log("你好${this.name}");
console.log(`${this.name} say hi`);
}
}
// 子级继承
// extends:继承
class Student extends Person {
constructor(name,age,sex) {
// super() 是继承父级的属性,如果括号里没内容,那么将不会继承
super(name,age);
this.sex = sex;
}
learn() {
console.log(
`我是${this.name},今年${this.age}岁,${this.sex},在学习英语`
)
}
}
// 实例化
// let zhangsan = new Person("张三", 18);
let zhangsan = new Student("张三", 18,"男");
zhangsan.sayHello()
zhangsan.learn()
// instanceof:判断继承关系,结果是布尔值
console.log(zhangsan instanceof Student);
console.log(zhangsan instanceof Person);
console.log(Person instanceof Object);
console.log(zhangsan instanceof Object);
console.log(zhangsan instanceof Array);
// 原型,原型链
console.log(zhangsan.__proto__);// 隐式原型 每个实例都有一个隐式原型
console.log(Student.prototype);// 显式原型 每一个实例上面都有一个显式原型
console.log(zhangsan.__proto__ === Student.prototype);
// 复习class基础语法
// ● class // 在这里是声明一个类的作用
// ● construct // 构造函数,声明类的时候必须要有
// ● extends // 继承
// ● super // 是继承父级的属性,如果括号里没内容,那么将不会继承
// ● instanceof // 判断继承关系,结果是布尔值
</script>
</body>
</html>