1.箭头函数
箭头函数是匿名函数,一般作为参数传递
let test = function(a,b) {
let sum = a + b;
return sum;
}
let test = (参数) => {函数体}
1.如果函数体只有一句,那么可以省略{},同时默认会返回函数体的结果,不能写return 2.如果只有一个参数,那么可以省略() 3.如果没有参数,()也不能省略
如果要通过箭头函数返回对象,需要用return的方式的方式来返回对象
如:const newArr = arr.map(value=>{
return {name:value}
})
还可以右边添加小括号:如:const func1 = (num) => ({a:123});
2.常见的数组方法
forEach()
forEach() 数组每一元素都执行一次回调函数 = 类似以前的for forEach 高阶函数
for循环可以通过break来打断、forEach不能通过break打断
用法 const arr = ['a', 'b', 'c'];
打印数组中的每一个值
arr.forEach(value => console.log(值 是 ${value}))
map()
用法 通过指定函数处理数组的每个元素,并返回处理后的数组。
function map() {
const texts = ['刘德华', '郭德纲', '林志'];
const newTexts = texts.map(value=><div>${value}</div>);
// 转成字符串
const html = newTexts.join('');
document.body.innerHTML = html;
}
every()
检测数值元素的每个元素是否都符合条件。
用法 const arr = [true, true, true, true, true];
const result = arr.every((value) => {
if (value === true) {
return true;
} else {
return false;
}
});
console.log(result);
}
some()
检测数组元素中是否有元素符合指定条件。至少一个满足
filter()
检测数值元素,并返回符合条件所有元素的数组。
过滤, 过滤出满足条件的数据
用法 const arr = [1, 2, 3, 4, 5, 6, 7];
// 返回 奇数
方式一 // const newArr = arr.filter((value) => {
// 如果你return 了 true 表示当前的value你想要
// if (value % 2 !== 0) {
// value 1 2 3 4 5 6
// value%2!==0 value=[1,3,5,7]
// 奇数
// return true; 方式一等价方式二
// } else {
// return false;
// }
// });
方式二// const newArr = arr.filter((value) => value % 2 !== 0);
console.log(newArr);
}
find()
返回符合传入测试(函数)条件的数组元素。
findIndex()
返回符合传入测试(函数)条件的数组元素索引。
includes()
判断一个数组是否包含一个指定的值。
indexOf()
搜索数组中的元素,并返回它所在的位置。
isArray()
判断对象是否为数组。
join()
把数组的所有元素放入一个字符串。
reduce()
将数组元素计算为一个值(从左到右)。
reverse()
反转数组的元素顺序。
sort()
对数组的元素进行排序。
伪数组转真数组
const lis = document.querySelectorAll('li');
// 转成真正的数组 一堆方式
// const liList = [].concat(lis);
// 现在先简单用一个
// const liList=[...伪数组]
const liList=[...lis];// 最简单的转伪数组的方式 先这么用
创建对象的几种方式
字面量
- 简单粗暴
- 不适合创建多个同样类型的对象的场景
如:const obj = { name:"悟空", height:100, age:5000};
工厂函数
- 容易理解
- 失去血缘关系
- 后期无法实现继承
{name:"八戒", age: 18, height: 5000}
{name1: "悟能", age1:83, height1: 231, grade: 3}
createStudent2 {name: "悟能", age 83, height: 231, grade: 3}
构造函数
-
可以方便的创建对象
-
拥有血缘关系
-
还有后续更多的优势
用法
// 1 声明函数 function createStudent(name, age) { // 2 通过 this 赋值 this.name = name; this.age = age; }
// 3 通过 new 来创建对象 const obj = new createStudent("悟能", 83);
console.log(obj);
构造函数的工作原理:
- 开辟空间
- 将新的创建的对象对象构造函数中的this
- 为对象赋值
- 将创建好的对象的地址返回
构造函数的弊端
同一个 say 方法占据了两份内存
function createStudent(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this.name);
}
}
const obj = new createStudent("悟能", 83);
const obj1 = new createStudent("悟能1", 84);
console.log(obj.say === obj1.say); // false 不是同一say方法 浪费了内存
提取同一个 say 方法
1解决了浪费内存的弊端 2但是造成了 污染全局变量 的问题
用法
// 提前将say 声明好
function say() { // 污染全局变量
console.log(this.name);
}
function createStudent(name, age) {
this.name = name;
this.age = age;
this.say = say
}
const obj = new createStudent("悟能", 83);
const obj1 = new createStudent("悟能1", 84);
console.log(obj.say === obj1.say); // true
在构造函数的原型上 存放函数(prototype)
- 解决了同一个
say浪费 内存的问题 - 解决了污染全局变量的问题
用法
function createStudent(name, age) {
this.name = name;
this.age = age;
}
// 将刚才的全局函数say 直接挂载到 构造函数的原型上 即可
// prototype 是个对象 每一个构造函数都会内置有的. 我们称之为原型
createStudent.prototype.say = function () {
console.log(this.name);
}
const obj = new createStudent("悟能", 83);
const obj1 = new createStudent("悟能1", 84);
console.log(obj.say === obj1.say); // true
原型链继承
利用代码的能力实现 面向对象的特性 封装 和 继承
-
子类strudent 继承了父类 Person的属性
// 父类 function Person(name, height) { this.name = name; this.height = height; }
Person.prototype.say = function () { console.log(this.name); console.log(this.height); }
// 子类 function Student(grade, name, height) { // 借用了父类的构造函数,完成对自己的赋值 Person.call(this, name, height) this.grade = grade; }
// 赋值了父类原型上的所有的 属性和方法 Student.prototype = Person.prototype; // 修改之类的指向 Student.prototype.constructor = Student;
// 创建子类的实例 const stu = new Student("一年", "周星星", 170); stu.say();
函数参数胡默认值
定义函数的同时,可以给形参一个默认值
// 定义函数的同时,可以给形参一个默认值
function show(msg = "大家一起快活呀") {
console.log(msg);
}
show();// 打印 大家一起快活呀
show("搞笑不");// 打印 搞笑不
对象简写
在定义对象的时候,如果属性名和变量名一直,那么可以实现简写
const name = "悟空";
const skill = "72变";
const say = function () { }
const obj = {
name, skill, say
}
console.log(obj);// {name:"悟空",skill:"72变",say:function(){}}
对象的方法也可以简写
say: function () {
console.log("say");
},// 常规写法
const obj = {
say() {
console.log(this);
}
}
解构(数组,对象)
提供更加方便获取数组中元素或者对象中属性的写法
获取数组中的元素
const [a, b, c, d] = [1, 2, 3, 4];
console.log(a, b, c, d);// 1,2,3,4
元素交互顺序
const obj = {
name: "悟空",
skill: "72变",
say() { }
}
const { name, skill,say } = obj;
console.log(name, skill,say);// 悟空 72变 function(){}
拓展运算符 || 剩余运算符
通过 ...符号来获取剩下的参数
函数内获取
function show(a, ...all) { // 只能放最后
console.log(a);
console.log(all);
}
show(1);// 1 []
show(1, 2, 3);// 1 [2,3]
数组内获取
const [a, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(rest);// [2, 3, 4, 5]
对象内获取
const obj={
name:"悟空",
skill:"72变",
say(){}
}
const {name,...others}=obj;
console.log(name); // 悟空
console.log(others); // {skill: "72变", say: ƒ}
set(去重)
永远不会有重复元素的对象
可以理解为不重复的数组
const set = new Set([1, 5, 3, 4]);
set.add(5);
set.add(5);
console.log(set);
Set对象转为数组
const set = new Set([1, 5, 3, 4]);
set.add(5);
set.add(5);
console.log(set);
const arr = [...set];// 将set对象转数组
console.log(arr);
函数的四种调用模式
根据函数内部this的指向不同,可以将函数的调用模式分成4种
- 函数调用模式
- 方法调用模式
- 构造函数调用模式
- 上下文调用模式(借用方法模式)
函数调用模式
如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window
function fn(){ console.log(this);// 指向window } fn();
方法调用模式
当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象
const obj = { sayHi:function(){ console.log(this);//在方法调用模式中,this指向调用当前方法的对象。 } } obj.sayHi();
构造函数调用模式
如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上
function Person(){ console.log(this); } Person();//this指向什么? var p = new Person();//this指向p
方法借用模式(call,apply,bind)
call:call方法可以调用一个函数,并且可以指定这个函数的this指向
const RichWumon = {
name: "富婆",
say: function () {
console.log(this.name, " 我要重金求子");
}
}
const obj = {
name: "屌丝"
}
RichWumon.say(); // 富婆
RichWumon.say.call(obj); // 屌丝
call应用 将伪数组转成数组
let divs = document.querySelectorAll('div');
// let divs = document.body.children;
console.log(divs);
function change(nodelist) {
console.log(Object.prototype.toString.call(nodelist));
return Array.prototype.slice.call(nodelist);
}
apply 就是apply()方法接受的是一个包含多个参数的数组。而call()方法接受的是若干个参数的列表
可以利用apply 将 刚才的call 的代码修改一下
const RichWumon = {
name: "富婆",
say: function () {
console.log(this.name, " 我要重金求子");
}
}
const obj = {
name: "屌丝"
}
RichWumon.say(); // 富婆
RichWumon.say.apply(obj); // 屌丝
apply应用 简化方法
// 简化log方法
function log() {
// 不需要改变this
console.log.apply(console, arguments);
}
bind方法
**bind()**方法创建一个新的函数, 可以绑定新的函数的this指向
let name = '张三'; function Fn(){ this.age = 1;
console.log(this.name + this.age);
}
Fn(); // 张三 1
// 返回值:新的函数 // 参数:新函数的this指向,当绑定了新函数的this指向后,无论使用何种调用模式,this都不会改变。 let obj = { name:'小强', } const newFn = Fn.bind(obj); newFn(); // 小强 1
总结
1 bind call apply 都可以实现修改this指向
2 代码写法上有区别
1 obj.skill.call(person);
2 obj.skill.apply(person);
3 const func = obj.skill.bind(person);
func();
3 传递参数
1 obj.skill.call(person,参数1,参数2)
2 obj.skill.apply(person,[参数1,参数2])
3 const func = obj.skill.bind(person);
func(参数1,参数2)