原生js如何写一个类?

【序】今天又在翻看公众号:《前端大全》了,发现这样篇文章讲原生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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352