zoukankan      html  css  js  c++  java
  • 通过JavaScript原型链理解基于原型的编程

    零.此文动机

      用了一段时间的Lua,用惯了Java C++等有Class关键字的语言,一直对Lua的中的面向对象技术感到费解,一个开源的objectlua更是看了n遍也没理解其中的原理,直到看到了Prototype-based programming

    一.什么是基于原型的编程

      基于原型的编程是面向对象编程的一种形式,通过复制已经存在的原型对象来实现面向对象,无与基于类的编程较大的区别是没有Class关键字,但是有类的概念。基于原型的编程也可以理解成基于实例的编程。

      基于原型的系统可以在程序运行时对原型进行修改,基于类(Java, C+)的语言则很难实现这一点。这么说比较抽象,下面会对比基于原型的类(JavaScript)和基于类的编程区别。

    二.JavaScript中的类继承

      一.java中的类

       java实现类有现成的关键字class,用java实现一个动物类,并实现一个人类来继承动物类。

     1 class Animal {
     2     public Animal() {
     3         name = "Animal";
     4     }
     5     public String eat() {
     6         return "eat!";
     7     }
     8     public String name;
     9 }
    10 
    11 class People extends Animal {
    12     public People() {
    13         super();
    14         name = "people";
    15     }
    16 }

      二.JavaScript中的类

      JavaScript定义了少数的数据类型:null,undefined,Boolean,Number,Function,Object(对象)。每个对象都有类属性,但是不能通过.class来访问,只能通过.toString方法来访问。但是很多对象继承的toString()方法重写了,所以要调用Function.call()方法。

    1 object.prototype.toString.call("")
    2 //[object String]
    3 object.prototype.toString.call(1)
    4 //[object Number]
    5 object.prototype.toString.call([])
    6 //[object Array]
    7 function f(){}
    8 object.prototype.toString.call(new f())
    9 //[object Object]

      每个对象除了有类属性外,还有原型属性(__proto__),这个属性便是用来继承的,对对象属性的查询,若没有此属性,便到其原型中继续查找。比如有对象A和对象B,A.__proto__ = B,执行代码A.b,若A.b == null, 再查找B.b,若找到则作为A.b的返回,若没有找到则继续到B的原型中找,直到找到或原型(Ojbect.prototype.__proto__)为空。JavaScript中的面向对象需要写一整篇博文来捋顺,下面只写最基本的对象继承。同样是上面人继承动物的例子,JavaScript这么搞:

     1 var Animal = {
     2     name : "Animal",
     3     eat : function() {
     4         return "eat!"
     5     }
     6 };
     7 
     8 var People = {
     9     name : "People"
    10 }
    11 
    12 People.__proto__ = Animal;
    13 
    14 People.eat()
    15 // "eat!"
    16 People.name
    17 // "People"

      People.__proto__ = Animal,便是让People的原型为Animal,实现People对Animal的继承,People.eat()返回“eat!”.

      这种原型的继承有什么优点呢?我理解到的是可以进行运行中的类修改,比如下面的代码,程序运行中在想在基类中添加属性或方法,java就不能做到。

    1 //继续上面代码
    2 Animal.run = function () {
    3     return "Animal run";
    4 }
    5 People.run()
    6 // "Animal run"

    三.其他基于原型的语言

      C++中的类只是对象的布局的定义,其肯定不是基于原型的语言。

      那Java呢,Java中的类也是对象,那Java是不是基于原型的语言呢?不是!简单的判断Java提供了Class关键字……更关键的是Java是一种强类型语言,所以其不具有动态扩展性。

      个人觉得记忆原型的语言必须具备下面2个特点:

    • 弱类型
    • 动态可扩展  

      具备这两个特点的语言看着那么像脚本语言呢,是的,Lua,Tcl,Perl【1】都是基于对象的语言。Python比较特殊,其语言级别提供了Class关键字,但是它又满足弱类型与动态可扩展,这时就不要纠结它是不是面向原型的语言了,个人愿意认为它是基于类的语言,毕竟提供了Class关键字…… 这个貌似是让python看起来像是基于原型语言的东东。

    参考

    1. https://en.wikipedia.org/wiki/Prototype-based_programming
    2. http://www.cnblogs.com/winter-cn/archive/2008/06/02/1212167.html
    3. JavaScript权威指南第六版
  • 相关阅读:
    MindSpore 建立神经网络
    MindSpore 数据加载及处理
    MindSpore 初探, 使用LeNet训练minist数据集
    Ubuntu 20.04 Xrdp Black Screen Ubuntu 20.04 Xrdp 远程桌面黑屏
    基于Transformer的ViT、DETR、Deformable DETR原理详解
    Ubuntu 18.04 / 20.04 自定义锁屏时间
    Transformer中K 、Q、V的设置以及为什么不能使用同一个值
    Auto-Encoding Scene Graphs for Image Captioning
    Eureka中读写锁的奇思妙想,学废了吗?
    PostgreSQL-查询所有索引
  • 原文地址:https://www.cnblogs.com/BigFeng/p/4589980.html
Copyright © 2011-2022 走看看