Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/365.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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 理解为什么真正的原型继承比经典/伪原型继承更好,以及为什么我不应该';t使用;新";_Javascript_Oop_Inheritance_Prototype - Fatal编程技术网

Javascript 理解为什么真正的原型继承比经典/伪原型继承更好,以及为什么我不应该';t使用;新";

Javascript 理解为什么真正的原型继承比经典/伪原型继承更好,以及为什么我不应该';t使用;新";,javascript,oop,inheritance,prototype,Javascript,Oop,Inheritance,Prototype,读一些喜欢或喜欢的文章 从埃里克·艾略特那里,我想我从理论上理解了他们所有的论点。但在实践中,我没有看到这种模式的真正优势 让我们从两个代码段中看一下实现继承的两个实现 第一个是使用它是来自Aadit M Shah的脚本 在这个例子中,我们将使用。也是由Aadit M Shah制作的 实施1: var AugmentPerson = Object.augment(function() { this.constructor = function(name) {

读一些喜欢或喜欢的文章 从埃里克·艾略特那里,我想我从理论上理解了他们所有的论点。但在实践中,我没有看到这种模式的真正优势

让我们从两个代码段中看一下实现继承的两个实现

  • 第一个是使用它是来自Aadit M Shah的脚本
  • 在这个例子中,我们将使用。也是由Aadit M Shah制作的
  • 实施1

        var AugmentPerson = Object.augment(function() {
          this.constructor = function(name) {
              this.name = name;
          };
          this.setAddress = function(country, city, street) {
              this.country = country;
              this.city = city;
              this.street = street;
          };
        });
        var AugmentFrenchGuy = AugmentPerson.augment(function(base) {
          this.constructor = function(name) {
              base.constructor.call(this,name);
          };
          this.setAddress = function(city, street) {
              base.setAddress.call(this, "France", city, street);
          };
        });
        var AugmentParisLover = AugmentFrenchGuy.augment(function(base) {
    
          this.constructor = function(name) {
              base.constructor.call(this, name);
          };
    
          this.setAddress = function(street) {
              base.setAddress.call(this, "Paris", street);
          };
        });
        var t = new AugmentParisLover("Mary");
        t.setAddress("CH");
        console.log(t.name, t.country, t.city, t.street); //Mary France Paris CH
    
        var CreatePerson = {
            create: function (name) {
                this.name = name;
                return this.extend();
            },
            setAddress: function(country, city, street) {
                 this.country = country;
                 this.city = city;
                 this.street = street;
            }
        };
        var CreateFrenchGuy  = CreatePerson.extend({
            create: function (name) {
                return CreatePerson.create.call(this,name);
            },
            setAddress: function(city, street) {
                CreatePerson.setAddress('France', city, street);
            }
        });
        var CreateParisLover  = CreateFrenchGuy.extend({
            create: function (name) {
                return CreateFrenchGuy.create.call(this,name);
            },
            setAddress: function(street) {
                CreateFrenchGuy.setAddress('Paris', street);
            }
        });
    
        var t = CreateParisLover.create("Mary");
        t.setAddress("CH");
        console.log(t.name, t.country, t.city, t.street); //Mary France Paris CH
    
    在本例中,我们使用函数构造函数,而不是直接从对象继承

    实施2

        var AugmentPerson = Object.augment(function() {
          this.constructor = function(name) {
              this.name = name;
          };
          this.setAddress = function(country, city, street) {
              this.country = country;
              this.city = city;
              this.street = street;
          };
        });
        var AugmentFrenchGuy = AugmentPerson.augment(function(base) {
          this.constructor = function(name) {
              base.constructor.call(this,name);
          };
          this.setAddress = function(city, street) {
              base.setAddress.call(this, "France", city, street);
          };
        });
        var AugmentParisLover = AugmentFrenchGuy.augment(function(base) {
    
          this.constructor = function(name) {
              base.constructor.call(this, name);
          };
    
          this.setAddress = function(street) {
              base.setAddress.call(this, "Paris", street);
          };
        });
        var t = new AugmentParisLover("Mary");
        t.setAddress("CH");
        console.log(t.name, t.country, t.city, t.street); //Mary France Paris CH
    
        var CreatePerson = {
            create: function (name) {
                this.name = name;
                return this.extend();
            },
            setAddress: function(country, city, street) {
                 this.country = country;
                 this.city = city;
                 this.street = street;
            }
        };
        var CreateFrenchGuy  = CreatePerson.extend({
            create: function (name) {
                return CreatePerson.create.call(this,name);
            },
            setAddress: function(city, street) {
                CreatePerson.setAddress('France', city, street);
            }
        });
        var CreateParisLover  = CreateFrenchGuy.extend({
            create: function (name) {
                return CreateFrenchGuy.create.call(this,name);
            },
            setAddress: function(street) {
                CreateFrenchGuy.setAddress('Paris', street);
            }
        });
    
        var t = CreateParisLover.create("Mary");
        t.setAddress("CH");
        console.log(t.name, t.country, t.city, t.street); //Mary France Paris CH
    
    老实说,我正试图看到第二个实现的好处。但我不能。我看到的唯一更灵活的一点是,我们可以使用apply创建实例:

    var t=CreateParisLover.create.apply(CreateParisLover,[“Mary”])

    这确实给了我们更多的灵活性。但我们也可以这样做:

    然后我们可以:

    var t = AugmentParisLover.new.apply(AugmentParisLover, ["Mary"]);
    
    在灵活性、可重用性、难度等方面,真正的好处是什么。。。 因为如果你检查两种情况的表现。Object.create()比new慢得多:
    我很困惑。

    在JavaScript中,人们所谓的“伪经典”继承就是原型继承。这是JavaScript拥有的唯一一种继承。避免
    new
    类似于避免
    switch
    语句,因为您可以使用
    if/else if
    代替。当然你可以,有时你应该。其他时候,
    开关
    正是正确的选择。与
    新建
    对象相同。创建
    :在您正在做的事情中使用最好的一个

    对我来说,这有点主观(在我看来,整个“伪经典遗传是坏的”模因也是如此):

  • new
    适用于我上课的时候。我使用
    new
    和构造函数,因为它非常适合语言的设计方式。(是的,这种设计是不寻常的,但事实就是如此。)因此,如果我想要有代表人的对象,并且有共同的行为,我将使用
    Person
    构造函数,将行为(函数)分配给
    Person.prototype
    ,并使用
    new Person
    来创建它们。(我使用my使其更加简洁,并轻松处理一些层次结构的内容。)这是简单、熟悉、干净、清晰的:如果您看到
    newperson
    您就知道我正在创建一个新对象。(如果我不是——是的,有可能用构造函数违反预期——那么在我看来,我不应该首先编写构造函数。)

    当然,现在您可以定义一个生成器函数(
    createPerson
    buildPerson
    ,无论什么),该函数使用
    Object.create
    或类似函数执行相同的操作。如果人们喜欢这样做的话,我不反对这样做(只要函数名是明确的,它就会创建一些东西)。我确实对人们说“你不应该使用
    new
    ”好像这是一个客观的建议而感到不满;这是一种观点,一种风格建议

  • Object.create
    是我在做实例级工作时使用的。我在做一个项目,在一个复杂的树/图中有一堆对象。它们只是数据,没有行为。有时,我们需要尚未验证的数据,因此不应覆盖以前的数据。因此,容器引用了已验证的数据(
    verified
    )和未验证的数据(
    current
    )。为了避免代码中不必要的分支,容器始终具有两个引用,但在正常情况下,它们引用相同的对象(
    container.verified=container.current={};
    )。几乎所有的代码都使用当前的对象,因为几乎所有的代码都应该使用最新的信息。如果我们需要添加挂起的数据,我们会执行
    container.current=Object.create(container.verified)
    然后将数据添加到
    container.current
    。由于
    current
    的原型经过
    验证
    ,因此无需将所有旧数据复制到原型中,也无需到处复制数据。例如,立面的经典用法
    new
    对于这项工作来说是错误的工具,它只会妨碍工作


  • JavaScript的许多奇妙之处之一是,您可以同时拥有这两种选择。我一直在同一个项目中为不同的事情使用这两种方法。

    编程很像时尚。在潜意识里,大多数程序员编写的代码在他们看来都很美观。这就是Java程序员希望在JavaScript中实现经典继承的主要原因。是的,尝试在JavaScript中实现经典继承是一项艰巨的任务,但这并不能阻止人们这样做。这有点过分了,但人们仍然这样做,因为他们只是希望自己的代码看起来像类(例如)

    Eric和我一直在以同样的方式推广工厂函数而不是构造函数的使用。然而,从工厂到建设者的这种转变不仅仅是出于审美的原因。我们两人都试图改变JavaScript程序员的心态,因为在某些方面,我们都认为JavaScript存在根本性的缺陷。JavaScript中的
    new
    操作符就是这样一个方面。虽然它已经被破坏了,但它是语言的核心,因此无法避免

    底线是:

    如果要在JavaScript中创建原型链,则必须使用
    new
    。没有其他方法可以绕过它(除了
    。\uuuuuu proto\uuuuuu
    这是不受欢迎的)。

    有趣的是,您既不需要原型也不需要类来继承多个对象。使用对象合成可以实现强b
    defclass Point
        var x
        var y
    end
    
    val zeroPoint = Point new(x: 0, y: 0)
    
    def (this == Point) new (x is Int, y is Int)
        match x, y
            case 0, 0 then zeroPoint
            else this new(x: x, y: y)
        end
    end
    
    var origin = Point new(0, 0)
    val point = Point new(2, 3)
    
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    
    var zeroPoint = new Point(0, 0);
    
    Point.new = function (x, y) {
        return x === 0 && y === 0 ?
        zeroPoint : new Point(x, y);
    };
    
    var origin = Point.new(0, 0);
    var point = Point.new(2, 3);
    
    data Point = Point Int Int
    zeroPoint = Point 0 0
    origin = zeroPoint
    point = Point 2 3
    
    data Shape = Rectangle Point Point | Circle Point Int
    rectangle = Rectangle origin (Point 3 4)
    circle = Circle zeroPoint 3
    
    rectangle :: Shape
    circle :: Shape
    
    Rectangle :: Point -> Point -> Shape
    Circle :: Point -> Int -> Shape
    
    var Shape = {};
    
    Rectangle.prototype = Shape;
    
    function Rectangle(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }
    
    Circle.prototype = Shape;
    
    function Circle(p, r) {
        this.p = p;
        this.r = r;
    }
    
    var rectangle = new Rectangle(origin, Point.new(3, 4));
    var circle = new Circle(zeroPoint, 3);
    
    var Shape = {
        Rectangle: function (p1, p2) {
            var rectangle = Object.create(this);
            rectangle.p1 = p1;
            rectangle.p2 = p2;
            return rectangle;
        },
        Circle: function (p, r) {
            var circle = Object.create(this);
            circle.p = p;
            circle.r = r;
            return circle;
        }
    };
    
    var rectangle = Shape.Rectangle(zeroPoint, Point.new(3, 4));
    var circle = Shape.Circle(origin, 3);
    
    var Shape = {
        Rectangle: function (p1, p2) {
            return this.extend({
                p1: p1,
                p2: p2
            });
        },
        Circle: function (p, r) {
            return this.extend({
                p: p,
                r: r
            });
        }
    };
    
    var rectangle = Shape.Rectangle(zeroPoint, Point.new(3, 4));
    var circle = Shape.Circle(origin, 3);
    
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F;
    };
    
    Object.create = function (o) {
        return new o.constructor;
    };
    
    function defclass(prototype) {
        var constructor = function () {};
        constructor.prototype = prototype;
        return constructor;
    }
    
    var Shape = defclass({
        rectangle: function (p1, p2) {
            this.p1 = p1;
            this.p2 = p2;
            return this;
        },
        circle: function (p, r) {
            this.p = p;
            this.r = r;
            return this;
        }
    });
    
    var rectangle = (new Shape).rectangle(zeroPoint, Point.new(3, 4));
    var circle = (new Shape).circle(origin, 3);
    
    var Shape = {
        Rectangle: function (p1, p2) {
            var rectangle = Object.create(this);
            rectangle.p1 = p1;
            rectangle.p2 = p2;
            return rectangle;
        },
        Circle: function (p, r) {
            var circle = Object.create(this);
            circle.p = p;
            circle.r = r;
            return circle;
        }
    };
    
    var rectangle = Shape.Rectangle.call(Shape, zeroPoint, Point.new(3, 4));
    var circle = Shape.Circle.call(Shape, origin, 3);
    
    function Rectangle(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }
    function Circle(p, r) {
        this.p = p;
        this.r = r;
    }
    
    Rectangle: function (p1, p2) {
        var rectangle = Object.create(this);
        rectangle.p1 = p1;
        rectangle.p2 = p2;
        return rectangle;
    },
    Circle: function (p, r) {
        var circle = Object.create(this);
        circle.p = p;
        circle.r = r;
        return circle;
    }
    
    var rectangle = Shape.Rectangle(zeroPoint, Point.new(3, 4));
    var circle = Shape.Circle(origin, 3);
    
    var Person = function() {
      var a = 5;
      this.method = function (b) { return a*b; };
    };
    var obj = new Person;
    obj.method(5); // return 25
    obj.a; // return undefined
    
    var Person = {
        a: 5,
        method: function (b) { return this.a*b; }
    };
    var obj  = Object.create(Person);
    obj.method(5); // return 25
    obj.a; // return 5
    
    var Person = function(a) {
      this.method = function (b) { return a*b; };
    };
    var obj = new Person(5);
    obj.method(5); // return 25
    
    var Person = {
        method: function (b) { return a*b; }
    };
    var obj  = Object.create(Person);
    obj.method(4); //Error
    
    var Animal = function Animal(name) {
      this.name = name;
    };
    
    Animal.prototype.walk = function walk() {
      console.log(this.name + ' goes for a walk.');
    };
    
    var Rabbit = function Rabbit(/* name */) {
      // Because construction and instantiation are conflated, you must call super().
      Animal.prototype.constructor.apply(this, arguments);
    };
    
    // Classical inheritance is really built on top of prototypal inheritance:
    Rabbit.prototype = Object.create(Animal.prototype);
    
    // Fix the .constructor property:
    Rabbit.prototype.constructor = Rabbit;
    
    Rabbit.prototype.jump = function jump() {
      console.log(this.name + ' hops around a bit.');
    };
    
    var myRabbit = new Rabbit('Bunny George');
    
    myRabbit.walk();
    // Bunny George goes for a walk.
    
    var animalMethods =  {
      walk: function walk() {
        console.log(this.name + ' goes for a walk.');
      }
    };
    
    var animal = function animal(name) {
      var instance = Object.create(animalMethods);
      instance.name = name;
      return instance;
    };
    
    var rabbitMethods = {
      jump: function jump() {
        console.log(this.name + ' hops around a bit.');
      }
    };
    
    var rabbit = function rabbit(name) {
      var proto = rabbitMethods;
    
      // This is more commonly done like mixin({}, animalMethods, rabbitMethods);
      // where mixin = $.extend, _.extend, mout.object.mixIn, etc... It just copies
      // source properties to the destination object (first arg), where properties from
      // the last argument override properties from previous source arguments.
      proto.walk = animalMethods.walk;
      var instance = Object.create(rabbitMethods);
    
      // This could just as easily be a functional mixin,
      // shared with both animal and rabbit.
      instance.name = name;
      return instance;
    };
    
    var rabbit2 = rabbit('Bunny Bob');
    
    rabbit2.walk();
    // Bunny Bob goes for a walk.