箭头函数
理解:一种简洁的函数简写
重点
()=>{
}
<script>
//普通函数--匿名
let func = function () {
console.log("456")
}
func()
//🔥箭头函数 简写 更简单 简洁
//🎃箭头不能拆开
let fun = () => {
console.log('123')
}
fun()
//🌈传递参数个数是一个时,小括号才可以被省略;其他都不行
//传递参数为0个,小括号不能省略
let fun1 = (a) => {
console.log(a)
}
fun1(12)
let fun3 = a => {
console.log(a)
}
fun3(2)
let fun2 = (a, b) => {
console.log(a, b)
}
fun2(7, 8)
// let fun4 = => {
// console.log(c)
// }
// fun4() 报错
//💥当箭头函数,函数体中只有一行代码的时候:
//1. 大括号可以省略;其他不行
//2. 默认返回 这行代码的运行结果🔥 (默认添加return)
let func4 = () => { console.log('098') }
func4()
let fun4 = () => console.log('098')
fun4()
//console.log()没有返回值,是undefined
let fun5 = () => { console.log('110') }
let fun6 = () => fun5()
console.log(fun6()) //结果显示 undefined
let fun7 = () => 110
let fun8 = () => fun7()
let result = fun8()
console.log(result) //结果显示110
//🌈箭头函数 🔥返回类型
let fun9 = () => 11; //返回值类型 数字 11
console.log(fun9())
let fun10 = () => "11"; //返回值类型 字符串 11
console.log(fun10())
let fun11 = () => [11, 10]; //返回值类型 数组 [11,10]
console.log(fun11())
🎃let fun12 = () => { }; //返回值类型 undefined
console.log(fun12())
//因为JS中 {} 意思不同
//两种意思:
// 大括号 对象 符号 返回类型对象
// 大括号 在函数内 包含==函数体==结构 符号 undefined 浏览器解析正解
//想要实现函数体 返回对象类型 🌈要加小括号
⚡let func1 = () => ({ a: 1 })
console.log(func1()) //返回值 { a: 1 } 类型:对象
</script>
解构
释义:获取数据的简写
可对复杂数据类型:数组,对象,函数(形参)简写
<script>
//高级写法
//查数组💥
const arr = ['a', 'b', 'c']
// const [str0,str1,str3] = arr
// console.log(str0,str1,str3) //结果 a b c
const [str1, str3] = arr //不是下标,[]里面变量任意命名,
//---------------------------按数组顺序查出
console.log(str1, str3) //结果 a b
//交换变量🔥
//传统 :两值交换 ,需要设置第三值 来交换
//高级:
let a = 100
let b = 200; //加分号 ,否则会报错
[a, b] = [b, a]
console.log(a, b)
//对象解构🎃
const obj = {
name: "金角",
height: 180
}
const { name, height } = obj; //获取属性
console.log(name, height) //得到属性值
//函数 形参
function fun1({ username }) {
console.log(username)
}
fun1({ username: '银角' })
</script>
简写
<script>
//对象简写🔥 常用
const username = '迪克'
const obj2 = {
username, /🔥/username=uaername 简写username
// 对象体 内 --函数简写
say() {
console.log("我是大魔王")
} //函数这样写在外面会报错
};
console.log(username);//==访问的是 obj2里面的username
console.log(obj2.username);
// 普通写法
function sing() {
console.log('我是小仙女')
}
sing();
// function show(a) {
// // if判断
// //三元
// a === undefined ? console.log('你好') : console.log('你很好')
// }
//突然感觉 赋传值很强大
function show(aa = "你好") { //默认值 你好
console.log(aa)
}
show();//你好
show("你很好")//你很好
</script>
… 运算符
通过 ...
符号来获取剩下的参数
剩余运算符
<script>
//剩余运算符 ...
/*对象🚀*/
const obj = { a: 1 }
const { a, ...b } = obj //a取a的值,b取除a以外的值
console.log(a) // 1
console.log(b) // 没有剩余的值,返回是空对象
//有值的话,返回的是带属性值的对象
// 数组同上
/*函数🍄 获取的 都是数组 */
function calc(...arr) {
console.log(arr) //返回值数组 [1,2]
}
calc(1, 2)
/* ...单独放,或者放后面*/
</script>
拓展、延展、展开运算符
//复杂类型传的是地址🎃
//... 是复制数据值
const list = [1, 2, 3, 4, 5, 6]
const newList = [...list] //复制数据
newList.push(7, 8)
console.log(list)
console.log(newList)
const obj1 = {
name: "大圣",
age: 180
}
//对象
// const obj2 = obj1
// obj2.height = "5000px"
// console.log(obj1)
// console.log(obj2) //obj1和obj2值一样
const obj2 = { ...obj1 }
obj2.height = 5000
console.log(obj1)
console.log(obj2)//obj1和obj2值不同
//数组合并
const list1 = [1, 2, 3]
const list2 = [4, 5, 6]
const list3 = [...list1, ...list2]
//对象-----注意:合并中
// 🌸🍁相同的属性名只能有一个,否则后面同名会覆盖前面的属性名
const obj3 = {
name: '八戒',
age: 200
}
const obj4 = {
name: '悟空',
height: 800
}
const obj6 = { ...obj3, ...obj4 }
console.log(obj6)
//{name: '悟空', age: 200, height: 800} 同名name属性被覆盖掉了
数组方法
方法 | 描述 |
---|---|
every() | 检测数值元素的每个元素是否都符合条件。 |
filter() | 检测数值元素,并返回符合条件所有元素的数组。 |
find() | 返回符合传入测试(函数)条件的数组元素。 |
findIndex() | 返回符合传入测试(函数)条件的数组元素索引。 |
forEach() | 数组每个元素都执行一次回调函数。 |
includes() | 判断一个数组是否包含一个指定的值。 |
indexOf() | 搜索数组中的元素,并返回它所在的位置。 |
isArray() | 判断对象是否为数组。 |
join() | 把数组的所有元素放入一个字符串。 |
map() | 通过指定函数处理数组的每个元素,并返回处理后的数组。 |
reduce() | 将数组元素计算为一个值(从左到右)。 |
reverse() | 反转数组的元素顺序。 |
some() | 检测数组元素中是否有元素符合指定条件。 |
sort() | 对数组的元素进行排序。 |
forEach()
遍历数组元素,两个值:值,下标
/* forEach 遍历 和for 遍历 功能很相似
forEach 遍历数组,接收一个回调函数;并且会在每一次遍历被使用
2.回调函数 会接收两个参数
1. 参数 被循环的元素
2. 参数 被循环的元素的下标 索引
3. 回调函数 修改为箭头函数 简洁
4. for循环 可以被break打断 被终止
break 不能打断forEach或终止
*/
const arr = ['a', 'b', 'c', 'd']
arr.forEach((item, index) => {
console.log(`元素本身${item} 下标${index}`)
})
some()
检测满足条件的元素,只有有一个满足,后面的就不在检测
//检测数组元素中是否有元素符合指定条件。
//找到一个满足条件,剩下的就不再遍历
// some() 🛕
/*
1 数组的方法 some 会遍历 数组
2 some 会接收 一个回调函数
3 回调函数 接收两个参数
1 参数一 元素本身
2 参数二 元素下标
4 some方法 就会返回 寻找的结果 true 或false🔥
如果我们在回调函数中 return 了 true => 找到满足条件的元素
*/
const arr1 = [
'绿色',
'绿色',
'绿色',
'红色',
'绿色'
];
let result = arr1.some((item, index) => {
console.log(index, item)
if (item === "红色") {
return true;
} else {
return false;
}
});
//根据判断条件进行简写,
//分析 判断一个值,传一个值,小括号可以缩写;
// 自带 返回值是=> 后面的;只有一行代码的时候,大括号也省略
let result2 = arr1.some(item => item === "红色")
//判断 有没有找到
if (result) {
console.log("找到红衣人")
} else {
console.log("安全")
}
every()
检测每个元素是否满足条件,全部满足返回true
//every 💢💥 检测每一个元素是否符合条件
/*
1 数组的方法 some 会遍历 数组
2 some 会接收 一个回调函数
3 回调函数 接收两个参数
1 参数一 元素本身
2 参数二 元素下标
4 some方法 就会返回 寻找的结果 true 或false🔥
如果我们在回调函数中 return 了 true => 找到满足条件的元素
*/
const arr2 = [
'绿色',
'绿色',
'绿色',
'红色',
'绿色'
];
let result1 = arr2.every((item, index) => {
console.log(index, item)
if (item === "绿色") {
return true;
} else {
return false;
}
});
if (result1) {
//全部通过
console.log('安全')
} else {
console.log('有问题')
}
join()
把数组转换成字符串
const arr = ['a', 'b', 'c']
let res = arr.map(item => `<p>${item}</p>`);
console.log(res)
let html1 = res.join('')
document.querySelector('div').innerHTml = html1
map()
数组改造成新数组
遍历通过指定函数处理数组的每个元素,重新返回处理后的新数组
1 数组的方法 map 会遍历 数组
2 map 会接收 一个回调函数
3 回调函数 接收两个参数
1 参数一 元素本身
2 参数二 元素下标
3 回调函数中 都需要返回一个改造好的元素
4 map函数会返回一个新数组 改元素中每一个元素 等于 回调函数中每一个返回的元素
**trim()**
方法
会从一个字符串的两端删除空白字符 ;当判断输入框是否为空的时候,可以用用
filter()方法
过滤符合条件的每一项,必须要return true或false 表示当前元素是否满足你的要求
filter 本身存在返回值 ,数组中存放满足条件的元素
find()方法
查找目标值
返回符合条件的目标值
findIndex()方法
查找目标值
找到返回索引值
找不到返回-1
includes()方法
判断是否包含指定的值
例如:在输入框中搜索 同姓 的人
<script>
/*
filter 检测数值元素,并返回符合条件所有元素的数组🔥
1. 会遍历每一个数组元素
2. filter 接收 回调函数
3. 回调函数 有两个参数
参数一 元素本身 元素下标
必须要return true或false 表示当前元素是否满足你的要求💥
filter 本身存在返回值 ,数组中存放满足条件的元素💥
*/
// const list = [19, 29, 39, 49, 59, 60, 80, 90, 88, 89, 83]
// const newList = list.filter((item) => item > 80)
// console.log(newList)
const list = ['王五', '贺一', '王四', '王三', '李子', '王二', '梅子', '王一'];
const inputs = document.querySelector('input')
const ul = document.querySelector('ul')
//input 事件 输入框发生变化 都会触发
//change事件 输入框发生变化,而且失去焦点,才会触发
inputs.addEventListener('input', function () {
//输入框 两边不能删除空白符的时候,为空的时候
if (!this.value.trim()) {
ul.innerHTML = '';
return
}
render()
})
function render() {
const value = inputs.value
//默认值 item.includes(value) 包含value值的
const filterList = list.filter((item) => item.includes(value));
const html = filterList.map((item) => `<li>${item}</li>`).join("")
ul.innerHTML = html
}
</script>
Set 对象
理解
不会有重复对象的元素 不是数组,但当成数组使用
const s=new Set()
Set也是一个构造函数
Set对象转为数组
const set = new Set([1, 5, 3, 4]); //将数组转成对象
set.add(5);
set.add(5);
console.log(set); //结果 Set(4) {1, 5, 3, 4} 对象类型,添加重复对象无效
const arr = [...set];// 再将set对象转数组 ...剩余运算符
console.log(arr);
例子
<body>
<input type="text" />
<ul></ul>
<script>
const input = document.querySelector('input');
const ul = document.querySelector('ul');
let arr = ['西瓜', '苹果'];
const renderHTML = () => {
let html = '';
arr.forEach((value) => (html += `<li>${value}</li>`));
ul.innerHTML = html;
};
renderHTML(); //基础渲染数据
//判断输入
input.addEventListener('keyup', function (event) {
// 按下回车
if (event.key === 'Enter') {
const arrs = new Set(arr) //筛选重复 对象
arrs.add(input.value) //加入对象
arr = [...arrs]
renderHTML();
}
});
</script>
</body>
面向对象
ES5
ES6
概念
项目级别,代码封装,代码设计的思想
特点
封装:
方便维护代码 ,实现业务需求
继承
多态
而在js中,面对对象只体现 封装 继承
对象在内存中的分配🔥
可看构造函数的应用
复杂数据类型 在栈中 存储的是地址
创建对象
字面量
理解看图 右边的设值 就是字面量
- 简单方便 用在小案例 复用代码
- 不适合创建多个同样类型的对象的场景
- 不好维护
工厂函数
- 容易理解 ;但是打印代码的时候,分不清出这个对象是属于谁,失去所属亲缘关系
- 无法复用功能;无法实现面对对象的两大特征:封装与继承
了解console.dir()
console.dir()是在控制台中查看指定JavaScript对象的所有属性的方法,开发人员可以通过它轻松获取对象的属性。
构造函数
理解:
制定了一种创建对象的模板;方便
- 本质是一个函数
- 命名 首字母大写
- 必须使用new 创建(实例化)对象,否则没意义
结合代码理解:
<script>
function Person() { //普通函数
//this 代表后面定义声明出来的 实例:p、s、n
this选中属性 赋值
this.name = "大圣"
}
const p = new Person() //new后 变成构造函数 首字母大写 使用new
//----------------通过构造函数所创建出来的这些实例--属性等 一模一样
const s = new Person()
const n = new Person()
console.log(p) // p变量是实例💥
// 个人理解 new 实例化对象
</script>
应用
<script>
function Render(username, height) {
this.name = username;
this.height = height
}
const p = new Render('11', 110)
const s = new Render('22', 220)
const w = new Render()//undefined;没有值或者只要一个值传递的时候,
缺少的属性值为undefined
console.log(p)
console.log(s)
console.log(w)
</script>
须知
- 笔试题比较常见
构造函数复用的时候,调用的是地址,所有在判断 内置对象中方法是否相等时,结果为true
代码
<script>
function Person(username, height) {
this.username = username;
}
const p1 = new Person('八戒1');
// const p2 = new Person('八戒2');
// 判断 p1 和 p2 在内存中 是否共用一个地址
// console.log(p1 === p2); false
const p3 = p1;
//判断 p1 和 p2 在内存中是否 共用一个地址
// console.log(p1 === p3); true
p3.username="悟空";
console.log(p1);
</script>
工作原理:
- 创建一个空对象,把它的地址赋值给this
- 把一些属性和方法添加到this上
- 把this的proto指向 构造函数的prototype
- 把this指向实例
构造函数的弊端
- 不同实例调用同一个方法,都会在栈中开辟一个空间,存储对应的数据地址;
🌈地址则指向放在堆中的方法属性,值等;
🔥这也就造成了内存消耗,复用一次方法,就占用一个新内存
代码:
function createStudent(name, age) {
this.name = name;
this.age = age;
this.say = function () { 构造函数中 有方法say
console.log(this.name);
}
}
const obj = new createStudent("悟能1", 83);
const obj1 = new createStudent("悟能2", 84);
一个 实例化 调用一次;多个调用多次,占用多个内存
console.log(obj.say === obj1.say); // false不是同一say方法 浪费了内存
解决内存消耗
将方法函数 写在构造函数体外面;可以理解为一个单独的个体,方法函数多次调用,存放地址不变
- 也造成了污染全局变量的问题
// 提前将say 声明好,单独写出来
function say() { // 污染全局变量
console.log(this.name);
}
function createStudent(name, age) {
this.name = name;
this.age = age;
this.say = say
}
const obj = new createStudent("悟能1", 83);
const obj1 = new createStudent("悟能2", 84);
console.log(obj.say === obj1.say); // true
原型技术
在构造函数的原型上 存放函数方法
同时解决了浪费内存问题和污染全局变量问题
prototype🔥
理解
- 原型的单词是
prototype
, 原型的这个名字是行业内共同认可的名字。 - 原型本质是一个对象,理解为
JavaScript
自动帮我们添加的 - 原型是
JavaScript
自动帮我们在定义构造函数
的时候添加的 - 所有构造函数的实例,共享一个原型,内置原型
prototype
,可添加 - 原型上一般是挂载函数
`
通用代码设计
<script>
通用代码 的设计
function Person() {
//💥在构造函数内部,只会定义一些 非函数类型的属性🔥(普通属性)
也就是实例.普通属性 都用this
this.name = '斑马';
this.height = 180
this.color = '白色'
}
//🌈方法 函数(行为) 全部定义在 构造函数的原型上🌸
Person.prototype.say = function () {
console.log('say 函数');
};
Person.prototype.toggle = function () {
console.log('toggle');
};
const p1 = new Person()
console.log(p1)
function Person(username, height) {
this.username = username
this.height = height
}
//原型上的方法也可以通过 this 来访问实例的属性
Person.prototype.sayName = function () {
console.log(this.username)
}
const p1 = new Person('wu空', 180)
const p2 = new Person('八戒', 180)
p1.sayName()
p1.sayHeight()
// console.log(p1)
// console.log()
// p1.toString() 原型--原型内置的函数
p2.sayName()
p2.sayHeight()
</script>
小整合代码
将以往正常实现功能需求的代码,利用构造函数封装起来,简化升级
思维养成!!!构思!!!
敲代码
实现:
<!DOCTYPE html>
<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>
<style>
div {
width: 100px;
height: 100px;
background-color: red;
margin: 100px 0 0 100px;
}
</style>
</head>
<body>
<button>按钮一:点击一下出现div效果</button>
<button>按钮二:点击一下div效果放大</button>
<script>
//使用构造函数 将实现功能封装起来
//获取button
const btn1 = document.querySelector('button:nth-Child(1)')
const btn2 = document.querySelector('button:nth-Child(2)')
//构造函数
function Drr() {
//实例.属性=。。。。。。
this.dom = document.createElement("div")
}
//避免消耗内存和污染全局变量,,使用原型prototype
// 构造函数名.原型.函数名 = function () {}
Drr.prototype.appendChild = function () {
//(插入的位置).appendChild(元素)
document.body.appendChild(this.dom)
}
Drr.prototype.scale = function () {
this.dom.style.transform = "scale(2)"
this.dom.style.transition = "3s"
}
//构造函数封装 功能函数
const a = new Drr()
//绑定点击事件
btn1.addEventListener('click', function () {
a.appendChild()
})
btn2.addEventListener('click', function () {
a.scale()
})
</script>
</body>
</html>
原型链继承
call()借调
借用别人的函数,给自己使用
可以修改this指向
a.方法.call(b) b调用了a的方法
体验
子类继承父类
<script>
function Parent(name, color, height, weight) {
// 本来 this的指向 = Parent 的实例!!
this.name = name;
this.color = color;
this.height = height;
this.weight = weight;
}
function Son(name, color, height, weight, money) {
// Son this 指向 Son的实例!!
// call() ehis借用了Parent方法 来给Son的实例 赋值!!!
🔥Parent.call(this, name, color, height, weight);
// 儿子 继承了父亲的属性
this.money = money;
}
Parent.prototype.say = function () {
console.log('这个是父亲的行为');
};
🔥Son.prototype.say = Parent.prototype.say;
// 儿子 继承 了父亲的行为 方法//下面有升级
const s= new Son(1,2,3,4,5);
console.log(s);
</script>
</body>
</html>
es5使用-面对对象
构造函数+原型+call来实现;
目前主流浏览器都通用;难
代码理解
<body>
<script>
function Parent(name, color, height) {
this.name = name;
this.color = color;
this.height = height;
}
Parent.prototype.say = function () {
console.log("这个是父亲的行为")
}//父类 可以有多种不同的方法
Parent.prototype.say = function () {
console.log("这个是父亲的行为")
}
function Son(name, color, height) {
//父亲的值 借调
Parent.call(this, name, color, height);
this.money = money
}
//子原型方法say=父原型方法say
// Son.prototype.say = Parent.prototype.say //一种方法,这样写可以,多种父方法继承就比较繁琐
// Son.prototype=Parent.prototype //子 继承父的原型链;但如果在子上添加方法,这样写也会增加父 的方法
//所以使用 剩余运算符...
Son.prototype = { ...Parent.prototype }
Son.prototype.a = function () { } //满足继承,又不影响父 的原型
console.log(Parent.prototype)
console.log(Son.prototype)
const s = new Son(1, 2, 3)
console.log(s)
</script>
</body>
案例优化体验:
<body>
<script>
// 父亲 共有 构造函数
function Element(tagName) {
// 创建元素
this.dom = document.createElement(tagName);
}
Element.prototype.appendBody = function () {
document.body.appendChild(this.dom);
};
// 儿子1
function DivElement(content) {
// this.dom = document.createElement('div');
💥Element.call(this, 'div');
this.dom.innerText = content;
}
💥DivElement.prototype = { ...Element.prototype };
// 儿子2
function ImgElement(src) {
Element.call(this, 'img');
this.dom.src = src;
}
ImgElement.prototype = { ...Element.prototype };
const divElement = new DivElement('这个是div的 内容');
setTimeout(() => {
divElement.appendBody();
}, 1000);
const imgElement = new ImgElement('./images/1.jpg');
setTimeout(() => {
imgElement.appendBody();
}, 2000);
</script>
</body>
</html>
es6 -面对对象
使用class类
很常用;简单
同时解决了内存消耗和污染全局变量的 问题
继承写法:
//class 首字母大写
class Parent{
//构造器🌸
constructor{
//super()写在构造器内部 //需要继承父类的话,可添加super()
super()🍄 //相当于调用父级的构造函数
}
//方法函数写构造器外面🎃
say(){
}
}
Code example理解
<script>
//简单常规写法
class DivElement {
🍁constructor(text) {
this.dom = document.createElement('div')
this.dom.innerHTML = text
}
//函数简写
appendBody() {
document.body.appendChild(this.dom)
}
}
console.dir(DivElement)
const divElement = new DivElement('添加成功')
setTimeout(() => {
divElement.appendBody()
}, 1000)
</script>
使用class类 继承
<script>
//父类
class Parent {
constructor(username) {
console.log("父类的构造器")
this.username = username
}
sau() {
console.log('父类中的方法')
}
}
//子类 extends 继承父类:
//1.不写构造器constructor,默认自己加构造器+并调用调用super(),===默认调用父类的构造器
// 2. 写构造器 里面调用super();
// 理解为父类的构造器===Person.call(this)
class Son extends Parent {
constructor(username, height) {
super(username) //使用super()就是调用父类的构造器constructor
this.height = height // 子类添加 新属性
}
fly() { // 子类添加 新方法
console.log('我会飞')
}
}
const s = new Son('儿子', 200) //new Son()就代表调用 构造器
console.log(s)
console.dir(Parent)
</script>
再次优化案例
<script>
//共有 父类
class Parent {
constructor(tagName) {
this.dom = document.createElement(tagName)
}
appendBody() {
document.body.appendChild(this.dom)
}
scale(rate) {
this.dom.style.transition = '1s'
setTimeout(() => {
this.dom.style.transform = `scale(${rate})`
}, 500)
}
}
class DivElement extends Parent {
constructor(text) {
super("div");
//调用父类的构造器
this.dom.innerHTML = text
}
}
class ImgElement extends Parent {
constructor(src) {
super('img');
this.dom.src = src
}
}
const divElement = new DivElement('div添加成功')
setTimeout(() => {
divElement.appendBody()
}, 1000)
const imgElement = new ImgElement('./images/1.png')
setTimeout(() => {
imgElement.scale(.3)
imgElement.appendBody()
}, 2000)
</script>
call bind apply
共同点与区别;面试常问
<script>
/*
call bind apply
1. 共同点:都可以修改 this 的指向
写法:1.1 call apply 直接使用 ; bind不能直接使用
obj.say.call(newObj)
obj.say.apply(newObj)
1.2 bind被使用的时候,不会直接调用原来函数的方法say,
而是会返回一个新函数,需要我们自己去调用
*/
/* 2. call 和 apply 区别 传递参数的写法 不同!!
1 obj.say.call(newObj,1,2); 在实例后面直接写值,逗号隔开
2 obj.say.apply(newObj,[1,2]); apply传递的是数组,需要用[]包裹值
3 (obj.say.bind(newObj))(1,2); bind在调用成功后,
(obj.say.bind(newObj,1,2))(); 值写在后面的小括号,或者和实例中的括号里,都可以比较随意
*/
const obj = {
username: "八戒",
say(a, b) {
console.log(this)
console.log(a, b)
}
};
const newObj = {
username: '悟空'
}
obj.say.call(newObj)
obj.say.apply(newObj)
obj.say.bind(newObj)❌❌❌
💛const newSay = obj.say.bind(newObj); // newObj
newSay(); 可以使用或者下一写法
🧡(obj.say.bind(newObj))(); // newObj
// obj.say.call(newObj,1,2);// 传参
// obj.say.apply(newObj,[1,2]);// 传参 数组
(obj.say.bind(newObj))(1,2);
</script>
检测数据类型
typeof--检测简单(基础)数据类型
instanceof---检测复杂数据类型(引用);
同时可以判断实例和构造函数的关系,
是通过new()出来的构造函数,返回true;
不是,返回false
<script>
//复杂数据类型 instanceof
function Person() {
}
function Pe() {
}
const p1 = new Person()
const p2 = new Pe()
console.log(p1 instanceof Person) //true
console.log(p1 instanceof Pe) //false
</script>
箭头函数没有 this指向
原型链
<script>
/*
原型链 一层关系 多个对象 可以通过 原型 技术 层层的关联
prototype 构造函数点出来
__proto__ 实例点
*/
// const div=document.querySelector("div")
// console.dir(div)
function Person() {}
const p1 = new Person();
// console.log(Person.prototype === p1.__proto__);
p1._
</script>
可参考 js高级