南京网站设计公司兴田德润可以不,手机网站模板免费下载,优秀网站建设,沧州网站建设公司JS原理-笔记#xff08;1/3#xff09;
知识点自测 今天课程中涉及到的已学习知识点 函数的call方法-文档链接
// 以指定的this调用函数#xff0c;并通过 从第二个参数开始依次传递参数
function func(food,drink){console.log(this)console.log(food)console.log(drink)…JS原理-笔记1/3
知识点自测 今天课程中涉及到的已学习知识点 函数的call方法-文档链接
// 以指定的this调用函数并通过 从第二个参数开始依次传递参数
function func(food,drink){console.log(this)console.log(food)console.log(drink)
}
const obj {name:小黑
}
func.call(obj,西蓝花,咖啡)函数的apply方法-文档链接
// 以指定的this调用函数并通过 数组的形式 传递参数
function func(food,drink){console.log(this)console.log(food)console.log(drink)
}
const obj {name:小黑
}
func.apply(obj,[西蓝花,咖啡])函数的bind方法-文档链接
function func(food, drink) {console.log(this)console.log(food)console.log(drink)
}
const obj {name: 小黑
}
const bindFunc func.bind(obj, 花菜)
bindFunc(可乐)剩余参数-文档链接
function func(...args){console.log(args)// 以数组的形式获取传入的所有参数
}
func(西蓝花,西葫芦,西洋参,西芹)Promise核心用法-文档链接
const p new Promise((resolve, reject) {setTimeout(() {const num parseInt(Math.random() * 10)if (num 5) {resolve(成功啦--${num})} else {reject(失败啦--${num})}}, 1000)
})
p.then(res {console.log(res)
}, err {console.log(err)
})URLSearchParams核心用法-文档链接
// 实例化时支持传入JS对象
const params new URLSearchParams({ name: jack, age: 18 })
// toString方法 返回搜索参数组成的字符串可直接使用在 URL 上。
console.log(params.toString())Object.create核心用法-文档链接 const person {name: itheima,foods: [西蓝花, 西红柿, 西葫芦]}// 将传入的对象作为原型创建一个新对象浅拷贝const clone Object.create(person)clone.name itheimaclone.foods.push(西北风)console.log(clone.foods person.foods)// trueObject.assign核心用法-文档链接 const person {name: itheima,foods: [西蓝花, 西红柿, 西葫芦]}const son {name: rose,}// 参数1 目标对象// 参数2 源对象// 将源对象的自身属性复制到目标对象并返回目标对象const returnTarget Object.assign(son, person)console.log(returnTarget son)// trueconsole.log(son.name)// itheimaconsole.log(son.foods person.foods)// trueJS中的this 这一节咱们来学习JS中this相关的知识点 传送门MDN-this 传送门MDN-call 传送门MDN-apply 传送门MDN-bind 传送门MDN-箭头函数 传送门MDN-剩余参数 传送门MDN-Symbol 这一节咱们会学习的有
如何确认this指向如何改变this指向手写callapplybind
如何确认this的值
在非严格模式下总是指向一个对象在严格模式下可以是任意值开启严格模式可以使用如下两种方式:
在整个脚本顶部开启在函数顶部开启
// 为整个脚本开启严格模式
use strict
function func() {// 为函数开启严格模式use strict
}然后就可以根据不同的模式来确认this指向啦 全局执行环境中,指向全局对象(非严格模式、严格模式) 函数内部,取决于函数被调用的方式 直接调用的this值: 非严格模式:全局对象(window)严格模式:undefined 对象方法调用的this值: 调用者
// 1.全局执行环境
// 非严格模式: 不做任何设置,直接写就是非严格模式
// console.log(this) // window
// 严格模式: 代码顶部加上 use strict 即可
// use strict // 为整个脚本开启严格模式
// console.log(this) // window// 2.函数内部
// 2.1 直接调用-非严格模式
// function func() {
// console.log(this) // 全局对象window
// }
// func()// 2.1 直接调用-严格模式
// function func() {
// use strict
// console.log(this) // undefined
// }
// func()// 2.2 对象方法调用
// const food {
// name: 猪脚饭,
// eat() {
// console.log(吧唧吧唧)
// console.log(this)
// }
// }
// food.eat()面试回答
如何确认this指向: 全局执行环境中,指向全局对象(非严格模式、严格模式) 如何开启严格模式: // 为整个脚本开启严格模式
use strict
function func() {// 为函数开启严格模式use strict
}函数内部,取决于函数被调用的方式 直接调用的this值: 非严格模式:全局对象(window)严格模式:undefined 对象方法调用时的this值为调用者
如何改变this指向
主要有2类改变函数内部this指向的方法 调用函数并传入具体的this: call: 参数1:this参数2-n:传递给函数的参数 apply-数组作为参数 参数1:this参数2:以数组的形式,传递给函数的参数 创建绑定this的函数: bind:返回一个绑定了this的新函数箭头函数:最近的this是谁,就是谁
调用函数并传入具体的this
function funcA(p1, p2) {console.log(funcA-调用)console.log(this)console.log(p1:, p1)console.log(p2:, p2)
}
const obj {name: jack
}
// call参数
// 参数1 this值
// 参数2-参数n 挨个传入函数的参数
funcA.call(obj, 1, 2)
// apply参数
// 参数1 this值
// 参数2 以数组的形式传入函数的参数
funcA.apply(obj, [3, 4])创建绑定this的函数
function funcB(p1, p2) {console.log(funcB-调用)console.log(this)console.log(p1:, p1)console.log(p2:, p2)
}
const person {name: itheima
}
// bind参数
// 参数1 this值
// 参数2-参数n 绑定的参数
const bindFuncB funcB.bind(person, 123)
bindFuncB(666)const student {name: lilei,sayHi: function () {console.log(this)// 箭头会从自己作用域链的上一层继承thisconst inner () {console.log(inner-调用了)console.log(this)}inner()}
}
student.sayHi()面试回答:
如何改变this指向,有2类改变this指向的方法,分别是: 调用函数时并传入具体的this call:从第二个参数开始挨个传递参数 apply:在第二个参数以数组的形式传递参数 创建函数时绑定this? bind:返回一个绑定了this以及参数(可选)的新函数 箭头函数:创建时会绑定上一级作用域中的this
手写call方法
这一节咱们来实现myCall方法实际用法和call方法一致核心步骤有4步
const person {name: itheima
}
function func(numA, numB) {console.log(this)console.log(numA, numB)return numA numB
}
// 参数1:指定的this值
// 参数2-参数n:原函数参数
const res func.myCall(person, 2, 8)
console.log(返回值为:, res)
如何定义myCall?如何让函数内部的this为某个对象如何让myCall接收参数2-参数n?使用Symbol调优myCall
// 1. 如何定义myCall
Function.prototype.myCall function () {// 逻辑略
}// 2 设置this并调用原函数
Function.prototype.myCall function (thisArg) {// this 是调用myCall的 函数// thisArg 指定的this// 为他添加一个自定义属性让函数成为他的该属性thisArg[fn] this// 调用并获取结果const res thisArg[fn]()// 移除添加的自定义属性delete thisArg[fn]}// 3 接收剩余参数并返回结果
Function.prototype.myCall function (thisArg, ...args) {thisArg[fn] this// 调用并获取结果const res thisArg[fn](...args)// 移除添加的自定义属性delete thisArg[fn]// 返回调用结果return res
}// 4 使用Symbol调优myCall
Function.prototype.myCall function (thisArg, ...args) {// 使用Symbol生成唯一标记避免和原属性冲突const fn Symbol()thisArg[fn] thisconst res thisArg[fn](...args)// 移除添加的自定义属性delete thisArg[fn]// 返回调用结果return res
}// --------测试代码--------
const person {name: itheima
}
function func(numA, numB) {console.log(this)console.log(numA, numB)return numA numB
}
// 参数1:指定的this值
// 参数2-参数n:原函数参数
const res func.myCall(person, 2, 8)
console.log(返回值为:, res)面试回答
手写call方法的步骤为
在function的原型上添加myCall方法,保证所有函数都可以调用方法内部,通过动态为对象添加方法的形式来指定this指向调用完毕之后通过delete关键字删除上一步动态增加的方法方法的名字通过Symbol进行设置,避免和默认名重复使用剩余参数的形式传递参数2-参数n(函数参数)
Function.prototype.myCall function (thisArg, ...args) {const fn Symbol()thisArg[fn] thisconst res thisArg[fn](...args)delete thisArg[fn]return res
}手写apply方法
这一节咱们来实现myApply方法实际用法和apply方法一致核心步骤依旧4步
const person {name: itheima’
}function func(numA, numB) {console.log(this)console.log(numA, numB)return numA numB
}const res func.myApply(person, [2, 8])
console.log(返回值为:, res) 如何定义myApply? 定义在原型上 如何让函数内部的this为某个对象 动态给对象添加方法,通过对象.方法()调用即可使用Symbol来生成方法名 如何让myApply接收参数? 定义参数2即可传递给原函数时需要使用...展开
// 1. 如何定义myApply
Function.prototype.myApply function () {// 逻辑略
}// 2 如何让函数内部的this为某个对象
Function.prototype.myApply function (thisArg) {// 为他添加一个自定义属性让函数成为他的该属性// 使用Symbol生成唯一标记避免和原属性冲突const fn Symbol()thisArg[fn] thisconst res thisArg[fn](...args)// 移除添加的自定义属性delete thisArg[fn]// 返回调用结果return res
}// 3 如何让myApply接收参数
Function.prototype.myApply function (thisArg, args) {const fn Symbol()thisArg[fn] this// 调用并获取结果// 用... 将args展开传入const res thisArg[fn](...args)delete thisArg[fn]// 返回调用结果return res
}// 测试代码
const person {name: itheima’
}function func(numA, numB) {console.log(this)console.log(numA, numB)return numA numB
}const res func.myApply(person, [2, 8])
console.log(返回值为:, res)
面试回答:
手写apply方法
在function的原型上添加myApply方法,保证所有函数都可以调用方法内部,通过动态为对象添加方法的形式来指定this指向调用完毕之后通过delete关键字删除上一步动态增加的方法方法的名字通过Symbol进行设置,避免和默认名重复直接使用数组传递函数的参数,内部调用时结合...运算符展开数组
Function.prototype.myApply function (thisArg, args) {const fn Symbol()thisArg[fn] thisconst res thisArg[fn](...args)delete thisArg[fn]return res
}手写bind方法
这一节咱们来实现myBind方法实际用法和bind方法一致核心步骤为2步
const person {name: itheima
}function func(numA, numB, numC, numD) {console.log(this)console.log(numA, numB, numC, numD)return numA numB numC numD
}const bindFunc func.myBind(person, 1, 2)const res bindFunc(3, 4)
console.log(返回值:, res)
如何返回一个绑定了this的函数如何实现绑定的参数及传入的参数合并?
// 1 如何返回一个绑定了this的函数
Function.prototype.myBind function (thisArg) {// myBind函数调用时this就是函数本身 return () {// 通过call方法将传入的 thisArg 作为this进行调用this.call(thisArg)}
}// 2 如何实现绑定的参数及传入的参数合并
// ...args 接收绑定参数
Function.prototype.myBind function (thisArg, ...args) {// ...args2 接收调用时的参数return (...args2) {// thisArg 需要指定的this// args 调用myBind时传入的参数// args2 调用新函数时传入的参数return this.call(thisArg, ...args, ...args2)}
}// 测试代码
const person {name: itheima
}function func(numA, numB, numC, numD) {console.log(this)console.log(numA, numB, numC, numD)return numA numB numC numD
}const bindFunc func.myBind(person, 1, 2)const res bindFunc(3, 4)
console.log(返回值:, res)
面试回答
手写bind方法
function原型上添加myBind函数,参数1为绑定的this,参数2-参数2为绑定的参数内部返回一个新箭头函数,目的是绑定作用域中的this返回的函数内部,通过call进行this和参数绑定通过call的参数2和参数3指定绑定的参数,和调用时传递的参数
Function.prototype.myBind function (thisArg, ...args) {return (...args2) {return this.call(thisArg, ...args, ...args2)}
}JS继承-ES5 这一节咱们来学习如何在JS中实现继承首先看看在ES6之前可以如何实现继承 传送门:继承与原型链 传送门:继承计算机科学 传送门:JavaScript高级程序设计 传送门:MDN-Object.create 传送门:MDN-Object.assign **继承**继承可以使子类具有父类的各种属性和方法而不需要再次编写相同的代码
这一节咱们会学习ES5中常见的继承写法(命名来源于 《JavaScript高级程序设计》)
原型链实现继承构造函数继承组合继承原型式继承寄生式继承寄生组合式继承
// 父类
function Parent(){this.name namethis.foods [西蓝花, 西红柿]this.sayFoods function () {console.log(this.foods)}
}ES5-原型链实现继承
**核心步骤**希望继承谁就将谁作为原型
**缺点**父类中的引用数据类型会被所有子类共享
// 父类
function Parent(name) {this.name namethis.foods [西蓝花, 西红柿]this.sayFoods function () {console.log(this.foods)}
}
// 子类
function Son() {
}
// 将父类的实例 作为子类的原型
Son.prototype new Parent(jack)
const s1 new Son()
s1.sayFoods()// [西蓝花, 西红柿]const s2 new Son()
s2.sayFoods() // [西蓝花, 西红柿]s2.foods.push(西葫芦)s2.sayFoods()// [西蓝花, 西红柿, 西葫芦]
s1.sayFoods()// [西蓝花, 西红柿, 西葫芦]面试回答
ES5-原型链实现继承
将父类的实例作为子类的原型实现继承这种继承方法的缺点是父类中的引用类型数据会被所有子类共享
ES5-构造函数继承
**核心步骤**在子类的构造函数中通过call或apply父类的构造函数
**缺点**子类没法使用父类原型上的属性/方法
// 父类
function Parent(name) {this.name name
}
Parent.prototype.sayHi function () {console.log(你好,我叫:, this.name)
}// 子类
function Son(name) {Parent.call(this, name)
}const s1 new Son(lucy)
const s2 new Son(rose)
s1.sayHi() // 报错面试回答
ES5-构造函数继承
在子类的构造函数中通过call或者apply调用父类的构造函数这种继承方法的缺点是:子类没法使用父类原型上的属性/方法
ES5-组合继承
通过组合继承,结合上面2种方法的优点
核心步骤
通过原型链继承公共的属性和方法通过构造函数继承实例独有的属性和方法
**特点**调用了2次构造函数
// 父类
function Person(name) {this.name name
}
// 方法加父类原型上
Person.prototype.sayHi function () {console.log(你好我叫${this.name})
}
// 子类构造函数
function Student(name, age) {// 调用父类构造函数传入thisPerson.call(this, name)// 子类独有的属性和方法单独设置this.age age
}
// 设置子类的原型为 父类实例
Student.prototype new Person()
// 调用子类的构造函数
const s new Student(李雷, 18)
// 可以使用原型链上的 属性和方法 也可以使用 通过构造函数获取的父类的属性和方法面试回答
ES5-组合继承 组合继承的核心步骤有2步: 通过原型链继承公共的属性和方法通过构造函数继承实例独有的属性和方法 组合继承的特点:调用2次父类的构造函数,浪费性能
ES5-原型式继承
直接基于对象实现继承
**核心步骤:**对某个对象进行浅拷贝(工厂函数或Object.create),实现继承
**缺点:**父类中的引用数据类型会被所有子类共享
// 可以用 Object.create替代
function objectFactory(obj) {function Fun() { }Fun.prototype objreturn new Fun()
}
const parent {name: parent,age: 25,friend: [rose, ice, robot],sayHi() {console.log(this.name, this.age)}
}
const son1 objectFactory(parent)
const son2 objectFactory(parent)
son1.friend.push(lucy)
console.log(son2.friend)面试回答:
ES5-原型式继承
原型式继承的核心步骤是:对某个对象进行浅拷贝,可以通过内置apiObject.create实现,不需要调用构造函数即可实现继承,主要针对于继承对象的情况原型式继承的缺点是:父类中的引用数据类型会被所有子类共享
ES5-寄生式继承
核心步骤:
定义工厂函数,并在内部:
对传入的对象进行浅拷贝(公共属性/方法)为浅拷贝对象增加属性/方法(独有属性/方法)
function createAnother(origin) {// Object.create基于原型创建新对象对属性进行浅拷贝const clone Object.create(origin)// 为对象增加属性/方法clone.sayHi function () {console.log(你好)}return clone
}
const parent {name: parent,foods: [西蓝花, 炒蛋, 花菜]
}
const son1 createAnother(parent)
const son2 createAnother(parent)面试回答:
寄生式继承 寄生式继承的核心步骤是:基于对象创建新对象(可以使用Object.create),并且为新创建的对象增加新的属性和方法 寄生式继承和上一节学习的原型式继承的区别是:创建出来的新对象,会额外的增加新的属性/方法
ES5-寄生组合式继承
所谓寄生组合式继承即通过借用构造函数来继承属性通过原型链的混成形式来继承方法。其背 后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数我们所需要的无非就是超类型 原型的一个副本而已。
核心步骤:
通过构造函数来继承属性通过原型链来继承方法
// 继承原型函数
function inheritPrototype(son, parent){const prototype object.create(parent.prototype)prototype.constructor sonson.prototype prototype
}// 父类
function Parent(name) {this.name namethis.foods [西蓝花, 西葫芦, 西红柿]
}Parent.prototype.sayHi function () {console.log(this.name, 我喜欢吃,${this.foods})
}// 子类借用父类的构造函数
function Son(name, age) {Parent.call(this, name)this.age age
}
// 完成原型继承
inheritPrototype(Son,Parent)
// 可以继续在原型上添加属性/方法
Son.prototype.sayAge function () {console.log(我的年龄是, this.age)
}const son1 new Son(jack, 18)
const son2 new Son(rose, 16)面试回答:
ES5-寄生组合式继承
寄生组合式继承的核心步骤是:通过构造函数来继承属性,通过原型链来继承方法寄生组合式继承和组合式继承的区别是:原型链的继承并没有调用父类的构造函数,而是直接基于父类的原型创建一个新副本实现继承
JS继承-ES6 这一节咱们来学习在ES6中class关键字的使用,并且使用它来实现继承 传送门:mdn类 传送门:阮一峰ES6-class 传送门:mdn-super ES6中推出了class类,是用来创建对象的模板.class可以看作是一个语法糖,它的绝大部分功能ES5 都可以做到新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
这一节咱们会学习:
class核心语法class实现继承class语法补充
class核心语法
核心语法:
如何定义及使用类:如何定义实例属性/方法:
// 定义类
class Person {// 实例属性方便一眼确认有哪些namefood// 构造方法类似于构造函数new的时候会调用内部的this就是实例化的对象constructor(name, food) {this.name namethis.food food}// 实例方法sayHi() {console.log(你好我叫${this.name},我喜欢吃${this.food})}
}
const p new Person(小黑, 西蓝花)
p.sayHi()面试回答:
class核心语法:
通过class 类名{}的形式来定义类内部直接写实例属性,可以设置默认值,实例方法的添加方式为方法名(){}构造函数通过constructor进行添加通过new 类名()创建实例,会调用构造函数constructor
class Person{namefood西兰花炒蛋constructor(name){this.namename}sayHi(){console.log(你好,我叫:,this.name)}
}
class实现继承
关键语法:
子类通过extends继承父类子类构造函数中通过super调用父类构造函数
// 在上一份代码的基础上继续编写下面代码
class Student extends Person {songconstructor(name, food, song) {// 子类构造函数使用this以前必须调用supersuper(name, food)this.song song}// 添加方法sing() {console.log(我叫${this.name},我喜欢唱${this.song})}
}
const s new Student(李雷, 花菜, 孤勇者)
s.sayHi()
s.sing()面试回答:
class实现继承
子类通过extends继承继承父类子类如果需要重新定义构造函数,必须在内部通过super关键字调用父类的构造函数
class私有,静态属性和方法
补充语法:
私有属性/方法的定义及使用(内部调用)静态属性/方法的定义及使用(类直接访问)
class Person {constructor(name) {this.name name}// 通过#作为前缀添加的属性会变为私有// 私有属性#secret 我有一个小秘密就不告诉你// 私有方法#say() {// 私有属性可以在console.log(私有的say方法)}info() {// 在类的内部可以访问私有属性调用私有方法console.log(this.#secret)this.#say()}// 通过 static定义静态属性/方法static staticMethod() {console.log(这是一个静态方法)console.log(this)}static info 直立行走双手双脚
}const p new Person(jack)
console.log(p)
// 外部无法访问 点语法访问直接报错通过[]无法动态获取
console.log(p[#secret])
p.info()
// 通过类访问静态属性/方法
Person.staticMethod()
console.log(Person.info)面试回答:
class语法补充 class中私有属性/方法 定义和使用时需要使用关键字#私有属性只能在类的内部使用,外部无法使用(代码中)Chrome的控制台中为了方便调试,可以直接访问 class中静态属性/方法 定义和使用时需要使用关键字static通过类访问静态方法中的this是类
fetch 这一节咱们来学习内置函数fetch 传送门-fetch 传送门-Response 传送门-Headers ajaxaxiosfetch的关系:
ajaxajax 是一种基于原生 JavaScript 的异步请求技术。它使用 XMLHttpRequest 对象来发送请求和接收响应。
axiosaxios 是一个基于 Promise 的 HTTP 客户端可以在浏览器和 Node.js 中使用。它提供了更高级别的封装使发送请求和处理响应更加简单和灵活。
fetchfetch 是浏览器内置的 API用于发送网络请求。它提供了一种现代化、基于 Promise 的方式来进行网络通信。用法和axios类似但相比于 axios它的功能和封装级别更为简单。
全局的fetch函数用来发起获取资源请求.他返回一个promise,这个promise会在请求响应后被resolve,并传回Response对象
这一节咱们会学习的有: fetch核心语法 fetch结合URLSearchParams发送get请求: const obj {name:jack,age:18
}
namejackage17fetch发送post请求,提交FormData数据 fetch发送post请求,提交JSON数据
fetch核心语法
核心语法:
如何发请求:如何处理响应:注:测试用接口
fetch(资源地址,{...配置项对象})
.then(response{// 接收请求
})面试回答:
fetch核心语法
fetch函数的参数: 参数1:请求的url地址参数2:以对象的形式设置请求相关的内容比如,方法,请求头,提交的数据等. fetch获取到响应结果,需要如何解析:
fetch(参数1,参数2)
.then(response{// 接收请求
})fetch结合URLSearchParams发送get请求:
需求:
使用fetch结合URLSearchParams调用地区查询接口
;(async function () {const params new URLSearchParams({pname: 广东省,cname: 广州市})const url http://hmajax.itheima.net/api/area?${params.toString()}// fetch函数返回的是 Promise对象通过await等待获取response对象const res await fetch(url)// .json方法返回的是Promise对象 继续通过await等待const data await res.json()
})()面试回答:
fetch结合URLSearchParams发送get请求:
fetch发送get请求时,不需要设置请求方法,因为默认的就是getURLSearchParams可以用来创建或者解析查询字符串,这里通过它将对象转为查询字符串
post请求-提交JSON
需求:
fetch发送post请求,提交JSON数据测试接口-用户注册
核心步骤:
根据文档设置请求头通过配置项设置,请求方法,请求头,请求体 ; (async function () {// 通过headers设置请求头const headers new Headers()// 通过 content-type指定请求体数据格式headers.append(content-type, application/json)// 参数1 url// 参数2 请求配置const res await fetch(http://hmajax.itheima.net/api/register, {method: post,// 请求方法headers, // 请求头// 请求体body: JSON.stringify({ username: itheima9876, password: 123456 })})const json await res.json()console.log(json)})()面试回答:
post请求-提交JSON
fetch函数的第二个参数可以设置请求头,请求方法,请求体,根据接口文档设置对应的内容即可可以通过JSON.stringify将对象转为JSON
post请求-提交FormData
需求:
fetch发送post请求,提交FormData数据(上传回显)测试接口-上传图片
核心步骤:
通过FormData添加文件通过配置项设置,请求方法,请求体(FormData不需要设置请求头) input typefile classfile acceptimage/*scriptdocument.querySelector(.file).addEventListener(change, async function (e) {// 生成FormData对象并添加数据const data new FormData()data.append(img, this.files[0])const res await fetch(http://hmajax.itheima.net/api/uploadimg, {method: post,body: data})const json await res.json()console.log(json)})/script面试回答: post请求-提交FormData fetch提交FormData时不需要额外的设置请求头 实例化FormData之后可以通过append(key,value)方法来动态添加数据 ajaxaxiosfetch的关系 ajax是一种基于原生JavaScript的异步请求技术,他使用XMLHttpRequest对象来发送请求和接收响应—学习原理时适用 axios是一个基于Promise的http客户端,可以在浏览器和Node.js中使用.他提供了更高级别的封装,使发送请求和处理响应更加简单和灵活—项目开发时适用 fetch是浏览器内置的API,用于发送网络请求.它基于Promise的方式来进行网络通信.和axios类似.但是功能和封装级别比axios更为简单—项目简单,不想导入axios时适用
Generator 这一节咱们来学习generator 传送门-Generator Generator对象由生成器函数返回并且它符合可迭代协议和迭代器协议.他可以用来控制流程,语法行为和之前学习的函数不一样
Generator-核心语法
核心语法:
如何定义生成器函数:如何获取generator对象yield表达式的使用通过for of获取每一个yield的值
// 1. 通过function* 创建生成器函数
function* foo() {// 遇到yield表达式时会暂停后续的操作yield ayield byield creturn d
}
// 2. 调用函数获取生成器
const f foo()
// 3. 通过next方法获取yield 之后的表达式结果会被包装到一个对象中
// 执行一次next 即可获取一次 yield之后的表达式结果
const res1 f.next()
console.log(res1)// {value: a, done: false}
const res2 f.next()
console.log(res2)// {value: b, done: false}
const res3 f.next()
console.log(res3)// {value: c, done: false}
// 最后一次可以拿到return的结果
const res4 f.next()
console.log(res4)// {value: d, done: true}
// done 为true之后获取到的value为undefined
const res5 f.next()
console.log(res5)// {value: undefined, done: true} // 4. 通过for of 获取每一个yield之后的值
const f2 foo()
for (const iterator of f2) {console.log(iterator)
}面试回答:
Generator-核心语法
可以通过生成器函数(function* xxx(){})来生成Generator对象:通过Generator对象的next方法可以获取yield表达式之后的结果
Generator-id生成器
**需求:**使用Generator实现一个id生成器id
function* idGenerator() {// 逻辑略
}
const idMaker idGenerator()// 调用next方法,获取id(每次累加1)
const { value: id1 } idMaker.next()
console.log(id1)
const { value: id2 } idMaker.next()
console.log(id2)核心步骤:
定义生成器函数内部使用循环,通过yield返回id并累加
// 1. 通过function* 创建生成器函数
function* generator() {let id 0// 无限循环while (true) {// id累加并返回yield id}
}
// 2. 调用函数获取生成器
const idMaker generator()
// 3. 需要id的时候 通过next获取即可
const { value: id1 } idMaker.next()
console.log(id1)
const { value: id2 } idMaker.next()
console.log(id2)面试回答:
Generator-id生成器
生成器函数内部的代码会在调用next方法时执行,利用这一特点,可以实现任意的生成器,需要时调用next即可获取结果
Generator-流程控制
遇到yield表达式时会暂停后续的操作
**需求:**使用Generator实现流程控制
function* weatherGenerator() {// 逻辑略yield axios()
}
// 获取Generator实例
const weather weatherGenerator()
// 依次获取 北上广深的天气 (axios)
weather.next()核心步骤:
yield后面跟上天气查询逻辑接口文档-天气预报参考code:北京 110100 上海 310100 广州 440100 深圳 440300 button classgetWeather天气查询/buttonscript srchttps://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js/scriptscript/*** 需求流程控制依次查询北上广深的天气预报* 参考code: 北京 110100 上海 310100 广州 440100 深圳 440300* 接口文档: https://apifox.com/apidoc/project-1937884/api-49760220* */function* weatherGenerator() {// 北京yield axios(http://hmajax.itheima.net/api/weather?city110100)// 上海yield axios(http://hmajax.itheima.net/api/weather?city310100)// 广州yield axios(http://hmajax.itheima.net/api/weather?city440100)// 深圳yield axios(http://hmajax.itheima.net/api/weather?city440300)}const cityWeather weatherGenerator()document.querySelector(.getWeather).addEventListener(click, async () {const res await genCity.next()console.log(res)})/script面试回答:
Generator-流程控制
使用Generator控制流程的本质是利用yield关键字来分隔逻辑比如示例中依次调用了多个接口,通过yield分隔,通过next来触发调用
参考资料
阮一峰-《ECMAScript 6 教程》图灵社区-JavaScript高级程序设计