爆火网络的js实战笔记,看完这篇文章,教你如何用原生js写一个类

一个类的主要组成部分有:类名,构造函数,属性,方法, 继承
在typescript中是这样的↓

 

import Vue from 'vue'
class foo extend Vue{
constructor(dogName:string){
  this.dog = dogName;
}
  public dog:string = 'husky'
  public dogSay(value){
  console.log(`dog say:${value}`)
}
}

相信大家很快就能够找到对应的部分,那么在js早期版本(指的是ES6之前的版本),是这么实现的呢?

 

function Animal(){}

function Dog(dogName){
  this.dog = dogName;
}
Dog.prototype.__proto__ = Animal.prototype
Dog.prototype.dogSay = function(value){
  console.log(`dog say:${value}`)
}

let myFoo = new foo('wangcai')
myFoo.dogSay('hello')

现在再来对号入座,是不是感觉能看懂又觉得不太懂,所以就引入下列问题

问题一

  • 【疑惑】构造函数哪里去了?
  • 【解惑】函数自身就成为构造函数

问题二

  • 【疑惑】既然本身是个构造,那么属性和方法存在哪里?
  • 【解惑】属性和方法是在执行完函数后才生成的,因此挂载到为实例分配的空间上,而this指针指向的是未来创建的实例。

问题三

  • 【疑惑】既然是存在未来的实例上,那么为什么方法要放到prototype中呢?
  • 【解惑】prototype可以理解为该类所创建的所有实例的共同的空间,如果放到this指针上,每生成一次实例都会多余分配一个函数所占用的空间,而放在prototype则在调用函数时才去prototype中取函数去执行。

问题四

  • 【疑惑】 既然是公共空间那为什么每个实例调用到的方法,方法中的this都指向调用的实例?
  • 【解惑】 因为在js中this的指向都是谁调用就指向谁

问题五

  • 【疑惑】既然prototype是个公共空间那么我们可以写如下代码吗?为什么?

 

function foo(dogName){
  foo.prototype.dog = dogName;
}
  • 【解惑】 如果是想要个普通的类属性的话,不可以,之前说过prototype是所有实例的公共空间,这样的话所有实例中的dog都改变了,但是可以作为类中的静态方法去使用

问题六

  • 【疑惑】 为什么继承要使用proto指向父级的prototype?而不是直接指向父级Animal?
  • 【解惑】 首先,Animal本身是一个构造函数,在new操作之后,实际生成的实例指向的是构造器的prototype,而之前说过prototype是一个公共空间,因此,新创建出来的实例并不直接等同于构造器的prototype,而是使用指针proto指向了父级的prototype

问题七

  • 【疑惑】 既然this指向实例,而实例不直接等同于prototype,那如何解释可以直接this到属性和方法?
  • 【解惑】 因为js的查找机制,如果this.dogSay 在this的prototype上找不到,那么就会沿着proto向上找,直到找到Object.prototype,如果都没有就返回null

问题八

  • 【疑惑】为什么proto在实例上是dog.__proto__,而在继承时构造函数上则是Dog.prototype.__proto__ = Animal.prototype
  • 【解惑】 原理是实例的proto与原型的proto实际上是两个不一样的指向,实例dog的proto指向的是Dog.prototype,
    而方法Dog的prototype.proto指向的是构造器,在new的时候实际上调用的是Dog.prototype.proto,也就相当于dog.proto.proto,如果我们将Dog的真实构造器的指向父级,那么new 的时候会根据proto一直找到父级的构造器

总结

原文提出的细则总是难以理解,我学习时喜欢找到最基础的因素并向外推导,因此我们需要先找到会核心的元素,一个函数,从它开始推导。

一个函数的组成部分:函数体,prototype空间,constructor构造器
一个实例的组成部分:实例本身的内存空间,实例的公共空间,
创建一个实例所需要的关键词:new
好的接下来大家能不能将过程再还原回来?
当我们new Dog()的时候发生了什么流程?
1.搜索new 通过Dog.prototype.proto找到了构造器方法

  1. 通过构造器方法创建了新的实例内存空间,实例中都有一个特殊方法proto,指向了实例的公共空间prototype
  2. 当调用实例的属性时,js就会再实例的空间查找,找不到就会顺着proto的指向去查找,如果都没有该属性就会返回null


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值