js高级:
一.Set:
-
永远不会有重复元素的对象: 可以理解为不重复的数组
<script> const set = new Set([1, 4, 6, 7]) set.add(1) set.add(4) //增加的不会重复,直接不会添加进去 console.log(set); //输出{1,4,6,7} </script>
Set对象转为数组:
<script>
const set = new Set([1, 4, 6, 7])
const arr = [...set] // 将set对象转数组
console.log(arr); //输出[1,4,6,7]
</script>
用set方法数组去重:
<input type="text" />
<ul></ul>
<script>
const input = document.querySelector('input');
const ul = document.querySelector('ul');
let arr = ['a', 'b'];
render();
input.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
// 去重处理
const set = new Set(arr)
set.add(this.value) //input.value
arr = [...set] //set对象转数组
render();
}
});
function render() {
const html = arr.map((value) => `<li>${value}</li>`).join('');
ul.innerHTML = html;
}
</script>
二.函数的四种调用模式:
根据函数内部this的指向不同,可以将函数的调用模式分成4种
- 函数调用模式
- 方法调用模式
- 构造函数调用模式
- 上下文调用模式(借用方法模式)
函数调用模式:
如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window
<script>
function fuc() {
console.log(this);// 指向window
}
fuc()
</script>
方法调用模式:
当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象
<script>
const obj = {
sayHi: function () {
console.log(this);//在方法调用模式中,this指向调用当前方法的对象。
}
}
obj.sayHi()
</script>
构造函数调用模式:
如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上
<script>
function Person() {
console.log(this);
}
Person() //this指window
const s = new Person(1) //this指Person
console.log(s);
</script>
方法借用模式:
也叫上下文模式,分为 apply 与 call
call方法:
call方法可以调用一个函数,并且可以指定这个函数的this指向
<script>
let obj = {
name: '小花',
say(age, sex) {
console.log(this.name + age + sex);
}
}
let afterObj = {
name: '小明'
}
obj.say(16, '女') //小花 16 女
obj.say.call(afterObj, 18, '男') //小明 18 男
</script>
apply方法:
就是apply()方法接受的是一个包含多个参数的数组。而call()方法接受的是若干个参数的列表
<script>
let obj = {
name: '小花',
say(age, sex) {
console.log(this.name + age + sex);
}
}
let afterObj = {
name: '小明'
}
obj.say(16, '女') //小花 16 女
obj.say.apply(afterObj, [18, '男']) //小明 18 男
</script>
bind方法:
**bind()**方法创建一个新的函数, 可以绑定新的函数的this指向
<script>
let obj = {
name: '小花',
say(age, sex) {
console.log(this.name + age + sex);
}
}
let afterObj = {
name: '小明'
}
obj.say(16, '女') //小花 16 女
const fuc = obj.say.bind(afterObj)
fuc(18, '男') //小明 18 男
</script>
</body>
三.es6 class(重点):
es6的class 的出现 基本上可以替代了es5的构造函数和原型,使之代码结构上更加简洁。
关键字:
- class
- 属性
- 方法
- 继承 extends
- 构造函数 constructor
- 方法重写 override:子类方法覆盖父类,super.父类方法()
- 父类的构造函数 super :子类有构造方法且使用this前,必须使用super()
es6面对对象:
<script>
// es6 面向对象 引出新的语法 类 class
class Person {
// 方法 constructor 在es6 构造函数
// constructor 会在 new Person的时候触发
constructor(name) {
// console.log("开始创建对象啦");
this.name = name;
}
// 直接写行为
say() {
console.log('say方法被调用啦 ' + this.name);
}
}
// 一样new一个对象
const p1 = new Person('悟空1');
const p2 = new Person('悟空2');
// console.log(p1);
// p1.say();
console.log(p1.say === p2.say); //true
// 属性
// 行为
class SuperMan {
constructor() {
// 对象有什么属性都写在 这里
this.name = '超人';
this.color = 'blue';
}
// 行为
say() {
console.log('说话');
}
fly() {
console.log('会飞');
}
sing() {
console.log('唱歌');
}
}
</script>
es6面对对象继承:
<script>
class Person {
constructor(name) {
this.name = name
}
say() {
console.log(this.name + '18岁');
}
}
// 表示学生要继承父亲
// extends 直接就实现了继承Person的方法
class Student extends Person {
constructor(name, sex) {
super(name) // 父亲的构造函数 =es5 Person.call(this,name);
this.sex = sex
}
}
const s1 = new Student('小花', '女');
console.log(s1); //小花 女
s1.say() //小花 18岁
// 1 如果你写了 extends 而且还写了 constructor 那你必须要在 constructor 调用了方法 super();
// 2 如果你只写了 extends 但是你没有写constructor 不需要管super
// 继承要继承父亲的属性和父亲的行为
// 1 只实现了继承父亲的行为 还没有实现继承父亲的属性 (super 表示可以继承父亲的属性)
</script>
es6三个定义方法的写法:
<script>
class Person {
// 性能最好 推荐方式!!
say1() {
console.log('say1');
}
say2 = function () {
console.log('s2');
};
say3 = () => {
console.log('s3');
};
}
const p1 = new Person();
const p2 = new Person();
console.log(p1.say1 === p2.say1); // true p1 和 p2 say1方法是同一个-节省内存
console.log(p1.say2 === p2.say2); // false p1 和 p2 say2方法不是同一个-性能不好
console.log(p1.say3 === p2.say3); // false p1 和 p2 say3方法不是同一个-性能不好
</script>
四.原型链:
<script>
// 1 创建数组的方式 有两种
// const arr = ['a', 'b', 'c']; // 字面量 常用-直接和简单的写法
// 2 数组 也是可以被new
// const arr = new Array('a', 'b', 'c');
// console.log(arr);
function Person() { }
const p1 = new Person();
// 在 Person的原型上添加一个方法
Person.prototype.show = function () {
console.log('自己添加的方法');
};
// p1.show();
// 给js内置的Array数据 原型也添加一个方法试试
Array.prototype.show = function () {
console.log('自定义的数组方法');
};
const arr = new Array('a', 'b', 'c');
// const arr = ['a', 'b', 'c'];
// arr.show();
// 利用原型对象的方式,在任意的构造函数上添加想要的行为
// 任意的构造函数 包括 自己定义的构造函数
// 也包括 js中 -内置就有的构造函数 Array
// arr.forEach
// arr.push()
// arr.map()
// arr.filter
// 对象的创建也分两种清空
// const ojb={};// 字面量 常用 直接 简单
const obj = new Object(); // 利用构造函数的方式来创建对象
Object.prototype.show = function () {
console.log('对象 自己的show方法');
};
obj.show();
</script>
五.修改原型链:
原型链 :
- 一个对象 它可以通过 prototype 来 找到被它继承父亲的方法
- 如果一个对象从底层触发 可以通过 prototype 一层一层往上找到 继承的关系
作用:
- 如果我需要给 某个数据 (字符串、数组、对象) 统一添加一个方法 ,可以直接在原型上添加
<script>
// // 万物皆对象
// Object.prototype.show = function () {
// console.log('这个是原型上的show方法');
// };
// // 你看要 dom对象 大哥大
// console.dir(document.querySelector("div"));
// console.log(obj);// 直接看到定义在自己身上的属性和方法 看不见定义在 原型对象上的属性和方法
Array.prototype.forEach = function () {
console.log("老子罢工了");
}
Array.prototype.map = function () {
console.log("老子罢工了");
}
const arr = [1, 2, 3];
arr.forEach(); // forEach 循环 到了你这个项目 这个知识用不了
</script>