Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
除了模仿经典类系统,JavaScript原型系统还能做什么?_Javascript_Prototype_Prototype Programming - Fatal编程技术网

除了模仿经典类系统,JavaScript原型系统还能做什么?

除了模仿经典类系统,JavaScript原型系统还能做什么?,javascript,prototype,prototype-programming,Javascript,Prototype,Prototype Programming,原型系统看起来比传统课堂系统灵活得多,但人们似乎对模仿传统课堂系统的所谓“最佳实践”感到满意: function foo() { // define instance properties here } foo.prototype.method = //define instance method here new foo() 一个原型系统必须具备所有的灵活性才能做其他事情 除了模仿类之外,原型系统还有什么用途吗?原型可以做什么样的事情?哪些类不能做,哪些类没有?原型系统通过标准对象实

原型系统看起来比传统课堂系统灵活得多,但人们似乎对模仿传统课堂系统的所谓“最佳实践”感到满意:

function foo() {
  // define instance properties here
}

foo.prototype.method = //define instance method here

new foo()
一个原型系统必须具备所有的灵活性才能做其他事情


除了模仿类之外,原型系统还有什么用途吗?原型可以做什么样的事情?哪些类不能做,哪些类没有?

原型系统通过标准对象实现继承,提供了一个迷人的模型。当然,这主要用于表示已建立的简单的实例类概念,但没有类作为需要特定语法来创建它们的语言级不可变结构。通过使用普通对象,您现在可以对“类”执行的所有操作(您也可以执行所有操作)——这就是您所说的灵活性

然后,这种灵活性被大量用于以编程方式扩展和更改类,仅使用JavaScript的给定对象变异功能:

  • 多重遗传的融合子和性状
  • 在实例化从原型继承的对象之后,可以修改原型
  • 高阶函数和方法装饰器可以轻松地用于原型的创建

当然,原型模型本身比仅仅实现类更强大。这些特性很少使用,因为类的概念非常有用且广泛,所以原型继承的实际功能并不广为人知(在JS引擎中也没有得到很好的优化:-/)

  • 关闭现有对象的原型可以极大地改变它们的行为。(随附全面支持)

  • 一些软件工程模式可以直接用对象实现。例如具有属性的,a包括动态链,哦,当然还有

    最后一个例子是带有默认值的选项对象。每个人都使用

      var myOptions = extend({}, defaultOptions, optionArgument);
    
    但更具活力的方法是使用

      var myOptions = extend(Object.create(defaultOptions), optionArgument);
    

    • 我认为原型继承系统允许更动态地添加方法/属性

      您可以轻松地扩展其他人编写的类,例如所有jQuery插件,还可以轻松地添加到本机类中,向字符串、数组和任何对象添加实用函数

      例如:

      也可以从其他类复制方法

      function myString(){
        this[0] = '42';
      }
      myString.prototype = String.prototype;
      
      foo = new myString();
      foo.first() // == '42'
      
      这还意味着您可以在从原型继承对象后扩展原型,但这些更改将被应用


      而且,就我个人而言,我发现原型非常方便和简单,在对象中布局方法对我来说非常有吸引力;)

      2013年6月,我回答了一个关于。从那以后,我花了很多时间思考继承问题,包括原型继承和古典继承,并且我写了大量关于继承的文章

      是的,原型继承的主要用途是模拟类。然而,它的用途远不止是模拟类。例如,原型链与范围链非常相似

      var foo = {};
      var bar = Object.create(foo);
      var baz = Object.create(bar);
      
      // chain: baz -> bar -> foo -> Object.prototype -> null
      
      function foo() {
          function bar() {
              function baz() {
                  // chain: baz -> bar -> foo -> global
              }
          }
      }
      
      原型范围同构 JavaScript中的原型和作用域有很多共同点。JavaScript中有三种常见的链类型:

    • 原型链

      var foo = {};
      var bar = Object.create(foo);
      var baz = Object.create(bar);
      
      // chain: baz -> bar -> foo -> Object.prototype -> null
      
      function foo() {
          function bar() {
              function baz() {
                  // chain: baz -> bar -> foo -> global
              }
          }
      }
      
    • 范围链

      var foo = {};
      var bar = Object.create(foo);
      var baz = Object.create(bar);
      
      // chain: baz -> bar -> foo -> Object.prototype -> null
      
      function foo() {
          function bar() {
              function baz() {
                  // chain: baz -> bar -> foo -> global
              }
          }
      }
      
    • 方法链

      var chain = {
          foo: function () {
              return this;
          },
          bar: function () {
              return this;
          },
          baz: function () {
              return this;
          }
      };
      
      chain.foo().bar().baz();
      
    • 在这三个链中,原型链和范围链最为相似。事实上,您可以使用该语句将原型链附加到范围链

      function foo() {
          var bar = {};
          var baz = Object.create(bar);
      
          with (baz) {
              // chain: baz -> bar -> Object.prototype -> foo -> global
          }
      }
      
      那么原型范围同构有什么用呢?一个直接用途是使用原型链对作用域链建模。这正是我为自己的编程语言所做的,我用JavaScript实现了它

      我首先定义了Bianca的全局范围,在一个文件中填充了一堆有用的数学函数,文件名如下:

      var global = module.exports = Object.create(null);
      
      global.abs   = new Native(Math.abs);
      global.acos  = new Native(Math.acos);
      global.asin  = new Native(Math.asin);
      global.atan  = new Native(Math.atan);
      global.ceil  = new Native(Math.ceil);
      global.cos   = new Native(Math.cos);
      global.exp   = new Native(Math.exp);
      global.floor = new Native(Math.floor);
      global.log   = new Native(Math.log);
      global.max   = new Native(Math.max);
      global.min   = new Native(Math.min);
      global.pow   = new Native(Math.pow);
      global.round = new Native(Math.round);
      global.sin   = new Native(Math.sin);
      global.sqrt  = new Native(Math.sqrt);
      global.tan   = new Native(Math.tan);
      
      global.max.rest = { type: "number" };
      global.min.rest = { type: "number" };
      
      global.sizeof = {
          result: { type: "number" },
          type: "function",
          funct: sizeof,
          params: [{
              type: "array",
              dimensions: []
          }]
      };
      
      function Native(funct) {
          this.funct = funct;
          this.type = "function";
          var length = funct.length;
          var params = this.params = [];
          this.result = { type: "number" };
          while (length--) params.push({ type: "number" });
      }
      
      function sizeof(array) {
          return array.length;
      }
      
      注意,我使用
      Object.create(null)
      创建了全局范围。我这样做是因为全局作用域没有任何父作用域

      之后,我为每个程序创建了一个单独的程序范围,其中包含程序的顶级定义。代码存储在一个名为的文件中,该文件太大,无法容纳一个答案。以下是文件的前三行:

      var parse = require("./ast");
      var global = require("./global");
      var program = Object.create(global);
      
      如您所见,全局范围是程序范围的父级。因此,
      程序
      继承自
      全局
      ,使范围变量查找与对象属性查找一样简单。这使得语言的运行时更加简单

      程序范围包含程序的顶级定义。例如,考虑下面的矩阵乘法程序,它存储在文件:

      顶级定义是
      添加
      。这些函数中的每一个都有自己的函数作用域,它继承自程序作用域。可在以下网站上找到该代码:

      例如,
      add
      的功能范围具有矩阵
      a
      b
      的定义

      因此,除了类之外,原型对于函数范围的建模也很有用

      代数数据类型建模的原型 类不是唯一可用的抽象类型。在函数式编程语言中,数据建模使用

      代数数据类型的最佳示例是列表:

      数据列表a=Nil | Cons a(列表a)
      
      该数据定义仅意味着a的列表可以是空列表(即
      Nil
      ),也可以是插入a的列表中的类型为“a”的值(即
      Cons a(列表a)
      )。例如,以下是所有列表:

      Nil::列表a
      Cons 1 Nil::列表编号
      Cons 1(Cons 2无)::列表编号
      欺骗