美文网首页HTML5
原生js如何写一个类?

原生js如何写一个类?

作者: 陌客百里 | 来源:发表于2020-08-25 23:55 被阅读0次

【序】今天又在翻看公众号:《前端大全》了,发现这样篇文章讲原生js的类的,讲的挺好的,就打算自己再借东风精简一下关键点,原文地址0

一个类的主要组成部分有:类名,构造函数,属性,方法, 继承
在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

相关文章

  • 原生js如何写一个类?

    【序】今天又在翻看公众号:《前端大全》了,发现这样篇文章讲原生js的类的,讲的挺好的,就打算自己再借东风精简一下关...

  • 原生js操作DOM元素的一些使用

    1、原生js给DOM元素添加一个类名 方法一: 使用DOM.setAttribute("class","类名") ...

  • WEEX H5 Render 解读(9)之sender类

    上节我们分析了stream.js的源码,这节我们继续阅读sender类。sender类提供了一个在原生调用js上提...

  • WebViewJavascriptBridge 使用记录

    现在的项目里面有WebView与js的交互,因为第一次用这个,走了弯路,特此记录 js调用原生 原生调用js, 类...

  • js给元素添加类的方法

    原生js中添加类的方法 .jquery中添加类的方法 检查是否含有某个类的方法 例子:html部分 css部分 js部分

  • 01jquery的基本认知

    1、 jQuery(JQ) jQuery是一个用原生js封装的js类库作用 大量直接操作DOM 解决兼容问题dom...

  • 原生JS添加类,删除类

    为 元素添加 class: document.getElementById("myDIV").classLis...

  • TypeScript - 04 类

    类 上面等同于原生js 继承 class A extends B,A类继承B类所有的属性和方法 子类通过 supe...

  • React-Native 导出 iOS 中自定义组件的方法

    要导出的原生组件是一个走势图的组件。 新建一个类,导出该组件 js 中新建一个 js 文件,对导出的组件进行封装 ...

  • jQuery

    一、jQuery初识 jQuery是一个js三方类库,与原生的js比较,用起来更简单方便。也有很大的优势,所以至今...

网友评论

    本文标题:原生js如何写一个类?

    本文链接:https://www.haomeiwen.com/subject/wiutsktx.html