专栏首页Nian糕的私人厨房聊聊原型 Prototype | 技术创作101训练营
原创

聊聊原型 Prototype | 技术创作101训练营

原型和原型链,一直是 JavaScript 中的重要概念,也是面试官必问的知识点,或许有的同学认为,自己虽然没有很深入了解过原型和原型链,但并不影响自己日常的开发工作,其实在我们日常开发工作中,很多的工具和框架已经做到了开箱即用的程度,不需要我们了解其原理就立即上手并投入生产当中,但这些工作换个人其实也能做,我们需要做的是,把自己修炼成独一无二、无可替代的那一个,这区别就在于“懂”和“用”之间的努力了。

万物皆对象

在 JavaScript 中,万物皆对象,记住这个概念,会对你理解原型和原型链有很大帮助,原型的定义在这里就不再复述,大家只要记住两点:

a. 每个函数 function 都有一个 prototype

b. 每个对象都有一个 __proto__,指向创建该对象的函数的 prototype

访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着 __proto__ 这条链向上找,这就是原型链,而 Instanceof 表示的就是一种继承关系,或是原型链的结构

A instanceof B 判断规则

沿着 A 的 __proto__ 这条线来找,同时沿着 B 的 prototype 这条线来找,如果两条线来找,如果两条线能找到统一引用,即同一个对象,那么就返回 true,如果找到终点还未重合,则返回 false

接下来我们来看一个完整的原型链图

原型和原型链.png

其中有些难理解的点,这里做一下简单分析:

a. 所有的引用类型都具有对象属性,Function 是一个对象,所以 Function instanceof Object === true

b. Object 自身是一个构造函数,函数都是继承自 Function,所以 Object instanceof Function === true

c. Function 是一个函数,函数是一种对象,也有 __proto__ 属性,既然是函数,那么它一定是被 Function 创建,所以 Function.__proto__ === Function.prototype

d. 对象的 __proto__ 指向的是创建它的函数的 prototype,所以 Object.__proto__ === Function.prototype

举个栗子

原型链在日常工作中用的也是非常多的,下面来实现一个简单的 zepto

function Elem(id) {
  this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val){
  var elem = this.elem
  if(val){
      elem.innerHTML = val;
      return this; // 链式操作
  }else {
      return elem.innerHTML;
  }
}
Elem.prototype.on = function(type, fn){
  var elem = this.elem;
  elem.addEventListener(type, fn)
}

既然说到了 zepto,那就来稍微拓展下 zepto 的源码,其实也很简单,也就三个部分——入口函数、构造函数、构造函数的原型,具体代码如下所示:

(function(window){
  var zepto = {}

  function Z(dom, selector) {
    var i, len = dom ? dom.length : 0
    for(i = 0; i < len; i++) this[i] = dom[i]
    this.length = len
    this.selector = selector || ''
  }
  
  zepto.Z = function(dom, selector) {
    return new Z(dom, selector)
  }

  zepto.init = function(selector) {
    var slice = Array.prototype.slice
    var dom = slice.call(document.querySelectorAll(selector))
    return zepto.Z(dom, selector)
  }

  // 即使用 zepto 时候的 $
  var $ = function(selector) {
    return zepto.init(selector)
  }

  Window.$ = $

  $.fn = {
    css: function(ley, value) {},
    html: function(value) {}
  }

  Z.prototype = $.fn
})(window)

最后来谈一下 Class,其本质还是语法糖,实现方式依旧是 prototype,但在语法上,Class 更贴近面向对象的写法,实现继承更加易读、易理解

function Animal() {
  this.eat = function() {
    console.log('this is animal')
  }
}
  
function Dog() {
  this.bark = function() {
    console.log('this is dog')
  }
}

Dog.prototype = new Animal()
var hhh = new Dog()
hhh.eat()
hhh.bark()

class Animal {
  costructor(name) {
    this.name = name
  }
  eat() {
    console.log(`this is ${this.name}`)
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name) // 必须写上!!!让Animal也有name参数
    this.name = name
  }
  bark() {
    console.log(`${this.name} bark`)
  }
}

const hhh = new Dog('哈士奇')
hhh.eat()
hhh.bark()

参考文章 继承与原型链 - JavaScript | MDN

Class的继承 - ECMAScript6 入门 | 阮一峰

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript this的指向

    在 JavaScript 中 this 取什么值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了,因为 this 的取值是执行上下文环境的一部分,每...

    Nian糕
  • Vue2.0 歌手列表滚动及右侧快速入口实现

    本次的系列博文的知识点讲解和代码,主要是来自于 黄轶 在慕课网的 Vue 2.0 高级实战-开发移动端音乐WebApp 课程,由个人总结并编写,其代码及知识点...

    Nian糕
  • JavaScript 获取 url 上的指定参数值

    假设现在有 A 和 B 两个页面,当我们从 A 页面跳转到 B 页面的时候,需要将 A 页面的两个值传递到 B 页面当中,前端可以通过读取缓存的方式,从 B 页...

    Nian糕
  • JQuery碎碎念

    IT故事会
  • 你被追尾了

    被追尾了,严格来讲,就是你的汽车和别人的汽车发生了碰撞. 所以本文来介绍一些检测碰撞的算法.

    ACM算法日常
  • 《JavaScript 模式》读书笔记(5)— 对象创建模式4

    JavaScript中没有常量的概念,虽然许多现代的编程环境可能为您提供了用以创建常量的const语句。作为一种变通方案,JavaScript中常见的一种方法...

    zaking
  • MVVM模式的理解

    MVVM全称Model-View-ViewModel是基于MVC和MVP体系结构模式的改进,MVVM就是MVC模式中的View的状态和行为抽象化,将视图UI和业...

    WindrunnerMax
  • Change Detection And Batch Update

    本文作者:IMWeb 吴浩麟 原文出处:IMWeb社区 未经同意,禁止转载 前言 在传统的WEB开发中,当与用户或服务器发生交互时,需要我们手动获取数...

    IMWeb前端团队
  • Change Detection And Batch Update

    在传统的WEB开发中,当与用户或服务器发生交互时,需要我们手动获取数据并更新DOM,这个过程是繁琐的、易错的。 特别是当页面功能过于复杂时,我们既要关注数据的变...

    IMWeb前端团队
  • Uncaught Error: _registerComponent(...): Target container is not a DOM element

    Uncaught Error: _registerComponent(...): Target container is not a DOM element

    一个会写诗的程序员

扫码关注云+社区

领取腾讯云代金券