js原型入门

前言

本文主要是根据《head first javascript程序设计》摘抄学习而成,学习采用这本书主要是一位阿里大佬的建议,经过近期的学习阅读,发现确实比其他的js书籍能更好的理解和使用js的相关知识。

对象图

为了更好地理解对象的结构,我们可以向后端学习,做出对象图,它基本是分为三栏的一个矩形图,第一栏是构造函数名称,第二栏是对象具有的属性,第三栏是对象具有的方法。

构造函数的效率

一般情况下,我们是使用构造函数进行一些类定义的,在构造函数中你会定义一些这个对象需要用到的属性或者方法。比如下面的Dog的代码。

function Dog(name,owner){
  this.name = name 
  this.owner = owner
  this.walk = function(){
    console.log("walking")
  }
}

var fido = new Dog("fido","xiaoli")
var fully = new Dog("fully","zhangmou")

重复的方法是问题么

在上述代码执行后,虽然代码层面,各个实例对象的属性以及方法都指定到了新的对象中,但细节发现,其属性是各自不同,可以理解,但是其方法也会都有一个函数的指向,这部分是重复的。那么这里就会涉及到一个内存的问题,因为每个实例对象都创建了自己的方法,重用方法的代码,会占据很多的内存,影响性能(尤其移动端)。

之所以出现这样的问题,是因为我们没有充分利用好js的对象模型,其是基于原型的概念的。

原型是什么

js可以从其他对象那里继承属性和行为,更具体的说js使用原型继承。其中其行为继承的对象称为原型对象。这个是指,会继承原型对象的属性(包括属性方法),同时在新对象中添加属性。

那么如果我们要定义一个小狗的原型,其对象图是什么样的呢?

这里需要注意的是:在小狗的原型中,其定义的属性和属性方法都要求是每个实例必然会用到且基本不会被更改或者重新定义的。

那么它的代码实现会怎么写呢?

Dog.prototype.type = 'animal'
Dog.prototype.bark = function(){
  console.log('barking')
}

继承原型

在有了原型对象之后,我们可以使用虚线来代表继承,发现新小狗实例对象都会通过继承的方式来使用原型对象的属性和方法,而不是重新赋值或者自建私有方法。

继承的工作原理

其继承的工作原理是查找关系: 1 编写代码,比如调用bark()

2 在实例对象中查找方法,没有找到

3 在实例对象中找不到,继续沿着继承链向上寻找

4 在小狗的原型中找到了 方法bark

5 在找到方法之后完成调用

总结:在使用原型继承之后,其会调用同一个bark方法,大量的节省了内存。这样不但能够重用代码,而且能新增属性和行为。

重写原型

那如果有些时候,我们需要重写bark方法,而不用原型中的方法呢?

答案肯定是可以的,我们可以在对象中重新定义自己的属性和方法,那么在继承的工作原理中,他就会现在实例对象中寻找,找到对应的方法之后就不会向上寻找原型对象的方法。

let little = new Dog("little",'xiaoli')
little.bark = function(){
  console.log('self bark')
}
little.bark()

关于this指向

我们之前有讲过,在原型对象中this是指向原型对象的,同样我们也很好理解在没有原型的时候,this调用指向的是对象本身,但是你在调用原型原型的方法时你可能认为this指向的是原型对象,其实并非如此。

调用方法时,this被设置为方法被调用的对象,即便在对象中找不到该方法,在原型中找到了方法,也不会修改其this的指向。

所以其准确的解释是在任何情况下,this指向的都是原始对象,即方法被调用的对象,在原型中也是如此。

我们可以通过代码进行验证:同时,虽然this指向的是原始对象,但并不影响其对原型对象的属性和方法的调用,这就是继承的本身。

Dog.prototype.name = 'default'
Dog.prototype.type = 'animal'
Dog.prototype.bark = function(){
  console.log(this)
  console.log(this.name+' is barking')
  console.log(this.name+' is '+this.type)
}
let little = new Dog("little",'xiaoli')
little.bark()

更多

更多的知识请参考下一篇文章《原型了解进阶》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 享元模式解读(1)

    本文是基于《javascript设计模式与开发实践》的享元模式相关章节整理实践而出,建议阅读时间为15-25min.

    RobinsonZhang
  • react进阶之render props

    Render props作为共享组件逻辑的一种有效模式,此模式借助state和辅助参数,可以提供ui的更好的灵活性。

    RobinsonZhang
  • 建造者模式解读

    RobinsonZhang
  • React父子组件传值

    版权声明:原创不易,多多珍惜 h...

    我乃小神神
  • C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

              C++反汇编第一讲,认识构造函数,析构函数,以及成员函数 以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数 ...

    IBinary
  • 如何编写自己的jQuery插件?

    对于那些不知道的人来说,jQuery是一个JavaScript库,它包含了许多特性,非常小而且速度很快。它还包括一个易于使用的API,在所有浏览器上都是兼容的,...

    liuxuewen
  • 微信小程序-音乐播放器+背景播放

    1.正常播放音频 2.可以滑动进度条 3.可以切换上一条,下一条音频 4.退出当前页或关闭小程序之后仍然可以正常播放 5.试听功能进入该播放页不可以播放上一条,...

    super.x
  • React 深入系列5:事件处理

    iKcamp
  • java队列

    队列为特殊的线性表,队列的特点先进先出(FIFO),队列插入为入队,队列删除为出对。

    mySoul
  • JavaScript实现简单的双向数据绑定

    双向数据绑定简单来说就是UI视图(View)与数据(Model)相互绑定在一起,当数据改变之后相应的UI视图也同步改变。反之,当UI视图改变之后相应的数据也同步...

    laixiangran

扫码关注云+社区

领取腾讯云代金券