原型链

原型链知识

prototype:只有函数有prototype属性,Object是构造函数,所以有该属性
proto:对象的原型。(a.proto===Object.getPrototypeOf(a))
proto是实例对象和构造函数之间的连接。它的值是构造函数的prototype
每个对象都有一个原型对象,对象的原型对象也可能是继承自其他的原型对象,一层一层以此类推,构成了原型链
原型链的终点就是Object.prototype
如a = new A() a.proto === A.prototype A.prototype.proto = Object.prototype
一图搞懂原型链
Object.setPrototypeOf() : 设定一个指定对象的原型 如Object.setPrototypeOf(A,B),将A的原型设置为B
Object.getPrototypeOf():获取一个对象的原型

image.png

继承

JS基础-完美掌握继承知识点

原理

复制父类的属性来重写子类的原型对象。

何为继承

使子类拥有父类的属性和方法,从而不需要编写相同代码。

原型链继承

原理 :sonFn.prototype = new fatherFn()
缺点

  • 父类this声明的属性被所有子类共享
  • 无法传参,不够灵活

    构造函数继承

    原理:在子函数中调用父函数,使用call改变this指向

    1. fatherFn(par){
    2. this.arr = par
    3. }
    4. sonFn(params){
    5. fatherFn.call(this,...params)
    6. }

    fatherF执行this指向类sonFn,所以fatherFn中的this声明都声明到sonFn下面了。
    缺点

  • 未对父类的prototype 做任何处理,所以无法继承父类prototype上的属性类方法。

  • 父类的方法无法复用。

    组合继承

    原理:利用原型链继承和构造函数继承 ```javascript fatherFn(params){ this.arr = params } fatherFn.prototype.name = ‘fatherFn 组合继承’ sonFn(params){ fatherFn.call(this,…params) //构造函数继承 } sonFn.protptype = new fatherFn() //原型链继承
  1. 能完整的继承父级函数的prototypethis<br />缺点
  2. - 两次调用父级,造成性能损耗
  3. - 生成两份父级的this
  4. - 父类的prototype上的属性和方法都在子类上,造成父类的原型链丢失
  5. <a name="hinYc"></a>
  6. #### 原型式继承
  7. 原理:通过Object.create() ,实现原理如下
  8. ```javascript
  9. function myCreate(obj){
  10. function F(){}
  11. F.prototype = obj
  12. return new F()
  13. }
  14. //使用
  15. let fatherObj = {name:'yhd'}
  16. let sonObj = myCreate(fatherObj) // sonObj 就可以继承fatherObj的内容

兼容性好,最简单的对象继承。
缺点:

  • 无法传参
  • 因为旧对象(oldObj)是实例对象(newObj)的原型,多个实例共享被继承对象的属性,存在篡改的可能。

    寄生式继承

    原理:基于原型式继承,封装一层函数,在函数中丰富对象 ```javascript // 基于前面的原型式继承 function fullCreate(obj){ let some = myCreate(obj) some.fn = function(){}//丰富函数 some.age = 18 return some }
  1. 专门为对象做某种固定方式的丰富。
  2. <a name="hgkU8"></a>
  3. #### 寄生组合式继承
  4. 原理:基于构造函数继承和寄生式继承<br />用寄生继承弥补构造函数继承未处理father.prototype的问题
  5. ```javascript
  6. function fatherFn(arr){
  7. this.name = 'father的Name'
  8. this.params = ...arr
  9. }
  10. fatherFn.ptototype.fn = 'father的prototype 上的fn'
  11. function sonFn(arr){
  12. this.name = 'son 的name'
  13. fatherFn.call(this,...arr) //将fatherFn中的this 指向 sonFn
  14. }
  15. function myExtends(son,father){
  16. //浅克隆father.prototype
  17. const fatherPrototype = Object.create(father.prototype)
  18. // 将son的prototype 继承father.prototype
  19. son.prototype = fatherPrototype
  20. // 修正constructor指向
  21. son.construtor = son
  22. }
  23. myExtends(sonFn,fatherFn)

寄生组合式继承式目前最成熟的继承方式,有如下优点

  • 只调用一次fatherFn函数、
  • 避免在子类prototype上创建不必要多余属性
  • 使用原型式继承父类prototype,保持了原型链上下文不变

    ES6 extends继承

    原理:寄生组合式继承
    1. // 寄生式继承 封装继承过程
    2. function _inherits(son, father) {
    3. // 原型式继承: 设置father.prototype为son.prototype的原型 用于继承father.prototype的属性/方法
    4. son.prototype = Object.create(father && father.prototype);
    5. son.prototype.constructor = son; // 修正constructor 指向
    6. // 将父类设置为子类的原型 用于继承父类的静态属性/方法(father.some)
    7. if (father) {
    8. Object.setPrototypeOf
    9. ? Object.setPrototypeOf(son, father)
    10. : son.__proto__ = father;
    11. }
    12. }

迭代器和生成器

ES6迭代器和生成器

迭代器(iterator)

含义:
为各种数据结构提供提供统一访问机制,任何数据结构只要部署 iterator接口,就能完成遍历操作。
作用:

  • 为各种数据结构提供统一访问接口
  • 使数据结构成员能按照一定顺序排列
  • 主要为for of服务

原生具备iterator接口的数据格式(可直接使用for…of..)

  • Array
  • map
  • set
  • string
  • 函数的arguments
  • Nodelist对象

    迭代器工作原理

  • 创建一个指针,指向数据机构起点

  • 第一次调用next()方法,指针自动指向数据结构第一个成员
  • 接下来不断调用next()方法,指针也不断后移,直到指向最后一一个成员
  • next()方法返回对象包含value 和done对象,{value:当前成员的值,done:布尔值}

value表示当前成员的值,done表示是否结束遍历
遍历结束时value返回undefined ,done返回true

  1. function myIterator (arr) {
  2. let arrIndex = 0
  3. return {
  4. next: function () {
  5. if (arrIndex > arr.length) {
  6. return {
  7. value: undefined,
  8. done: true
  9. }
  10. } else {
  11. arrIndex++
  12. return {
  13. value: arr[arrIndex - 1],
  14. done: false
  15. }
  16. }
  17. }
  18. }
  19. }
  20. const arr = ['a', 'b', 3, 'd']
  21. const iteratorFn = myIterator(arr)
  22. console.log(iteratorFn.next())
  23. console.log(iteratorFn.next())
  24. console.log(iteratorFn.next())
  25. console.log(iteratorFn.next())
  26. console.log(iteratorFn.next())

注意点:
for of不支持对象,对象的Symbol.iterator属性,指向该对象的默认遍历器方法。当使用for of去遍历某一个数据结构的时候,首先去找Symbol.iterator,找到了就去遍历,没有找到的话不能遍历,提示Uncaught TypeError: XXX is not iterable
当使用扩展运算符(…)或者对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法

生成器(Generator)

概念:

  • Generator函数是ES6提供的异步编程解决方案,语法行为于传统函数不同
  • Generator函数是一个状态机,封装了多种内部状态
  • Generator函数除了是状态机,还是遍历器对象生成函数
  • 可暂停函数,yield可暂停,next可启动,

分段执行

  1. function* myGenerator () {
  2. yield 111
  3. yield '22222'
  4. }
  5. const fn = myGenerator()
  6. console.log(fn.next())//{value: 111, done: false}
  7. console.log(fn.next())//{value: ‘22222’, done: false}

Generator 函数是分段执行的,调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true},再次调用next方法会从上一次停止时的yield处开始,直到最后。
next传递参数
yield本身返回undefined,当next() 携带参数,该参数会当作上一个yield的返回值
与iterator迭代器关系
generator本来就是遍历器生成函数,可以将generator赋值给对象的[symbol.iterator]属性,从而使得该对象具有iterator接口

  1. let obj = { username: 'kobe', age: 39 }
  2. obj[Symbol.iterator] = function* myTest() {
  3. yield 1;
  4. yield 2;
  5. yield 3;
  6. };
  7. for (let i of obj) {
  8. console.log(i) // 1 2 3
  9. }
  1. function iteratify(obj) {
  2. obj[Symbol.iterator] = function * () {
  3. for(let prop of Object.getOwnPropertyNames(this)) {
  4. yield this[prop]
  5. }
  6. }
  7. }

map filter reduce

promise
proxy