js高级三天

98 阅读7分钟

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};

工厂函数

  1. 容易理解
  2. 失去血缘关系
  3. 后期无法实现继承

{name:"八戒", age: 18, height: 5000}

{name1: "悟能", age1:83, height1: 231, grade: 3}

createStudent2 {name: "悟能", age 83, height: 231, grade: 3}

构造函数

  1. 可以方便的创建对象

  2. 拥有血缘关系

  3. 还有后续更多的优势

    用法

    // 1 声明函数 function createStudent(name, age) { // 2 通过 this 赋值 this.name = name; this.age = age; }

    // 3 通过 new 来创建对象 const obj = new createStudent("悟能", 83);

    console.log(obj);

构造函数的工作原理:

  1. 开辟空间
  2. 将新的创建的对象对象构造函数中的this
  3. 为对象赋值
  4. 将创建好的对象的地址返回

构造函数的弊端

同一个 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)

  1. 解决了同一个 say 浪费 内存的问题
  2. 解决了污染全局变量的问题

用法

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

原型链继承

利用代码的能力实现 面向对象的特性 封装继承

  1. 子类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种

  1. 函数调用模式
  2. 方法调用模式
  3. 构造函数调用模式
  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)