Object.create原型链 [英] Object.create Prototype Chains

查看:125
本文介绍了Object.create原型链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我读到了ECMAScript 5 Object.create()
我想用这种方法开始在我的代码中构建原型链设置原型及其构造函数,
我喜欢你可以直接设置可写配置等。

Yesterday i read about ECMAScript 5 Object.create() And I wanted to start building prototype Chains in my Code with this method instead of setting the prototype and its constructor, I like that you can directly set writable configurable etc..

我试过这样的

function printobject(msg, obj) {
    if (msg) {
        document.write("<b>" + msg + "</b><br>");
        document.write("<hr><br>");
    }
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (obj[prop].toString() !== "[object Object]") {
                document.write(prop + " : " + obj[prop] + "<br>");
            }
            else {
                document.write("<b>" + prop + " : " + obj[prop] + "</b><br>");
                printobject("", obj[prop]);
            }
        }
    }
    if (msg) {
        document.write("<br><hr><br>");
    }
};
var base = {
    extend: function () { //extend this Object
        var args = Array.prototype.slice.call(arguments);
        printobject("Arguments to Extend", args)
        var that = Object.create(this, (args ? args.shift() : {}));
        var arg = args.shift() || {};
        printobject("Copy Properties to New Object", arg);
        for (var prop in arg) {
            that[prop] = arg[prop];
        }
        // Object.freeze(that);       
        return that;
    },
    create: function () { //Creates new instances of the Object
        var that = Object.create(this, {
            extend: {
                value: null,
                writable: false,
                configurable: false
            }, //sets extend and create to null so you cant create a new instance when used create ( use extend instead);
            create: {
                value: null,
                writable: false,
                configurable: false
            }
        });
        that.init.apply(that, arguments); //call init function for the new created object; 
        return that;
    },
    init: function () {
        printobject("No Initfunction supplied for New Object", this);
    } // Empty init function for fallback
}
var Human = base.extend({
    name: {
        value: "test"
    }
}, {
    init: function (name) {
        alert(name + " has been created");
        this.name = name;
    },
    walk: function () {
        alert(this.name + " walks");
    }
});
var Human1 = Human.create("test2");
//alert("Human1 - Name:" + Human1.name);
Human1.walk();
Human.walk = function () {
    alert("Walk has been overwritten")
}; //Object freezed 
Human1.walk();
Human1.create = function () {
    alert("Overwrite create");
}; //Doesnt exist in created     Object
Human1.create(); ?




  • 执行 Human中给出的方法只在ram中存在一次?和 Human1.walk()指向它?

  • 我想知道这是否是这样做的正确方法?我对JavaScript比较陌生。

    • Do the methods given in Human only exist once in the ram? and Human1.walk() points to it?
    • I wonder if this is the right Approach of doing it like this? I'm relatively new to JavaScript.
    • 这是 jsfiddle

      首先,很多事情让事情变得清晰=)
      但是,
      1:当我这样做时,实例继承自构造函数的原型(?)

      First of all, thx a lot that made things def clearer =) But, 1: when I do it like this the instances inherit from their constructor's prototype (?)

       Nothing = {};
      function base() {
      this.inherit = function(constructor) {
          alert("inherit");
          var obj = constructor;
          obj.constructor = constructor;
          obj.prototype = this;
         return obj ;  
       }
       ;}
      base.prototype = Nothing;
      base.constructor = base;
      var Top = new base();       
      var Human = Top.inherit(function(name) {
              this.name = name;
      });
      var Paul = new Human("Paul");
      alert(Paul.name);
      alert(Paul instanceof Human); //true `
      

      2:因此instanceof运算符不会破坏此代码,(它适用于函数似乎对我来说很清楚)

      2: So the instanceof operator doesnt break in this Code , (that it works for functions only seems clear to me)

      但是这样编写,Paul仍然从Top的原型
      继承了inherit()方法,我需要覆盖它
      但是如果我不希望Human的实例继承该方法,我该怎么做?

      But written this way, Paul still inherits the inherit() method from Top's prototype and i would need to overwrite it But if i dont want the instance of Human to inherit the method, how do i do this ?

      除了使用Objkect之外,我不能设置像wrtable这样的属性描述符。 defineproperty(?)

      And i cant set property descriptors like wrtable except using Objkect.defineproperty (?)

      那么使用Object.create()从Objects继承的主要好处vs
      设置原型和构造函数? =)

      So what are the main benefits from using Object.create() to inherit from Objects vs Setting the prototypes and construcotrs ? =)

      3:哦thx,是的,那就是defs那不是基础对象的扩展=)
      thx的建议=)

      3: Oh thx, yes thats def right thats not an extension of base object =) thx for the suggestion =)

      所有努力的费用=)

      好的当我这样做时


      Nothing = {}

      Nothing = {}

      base.prototype = Nothing;

      base.prototype = Nothing;

      这不会阻止原型链直到Object.prototype吗?
      如果没有,有没有办法做到这一点? =)会(Object.create(null);)这样做,

      this doesnt prevent s.o to go up the prototype chain til Object.prototype ? if not , is there a way to do this ? =) Would ( Object.create(null); ) do this,

      我想我必须设置


      base.prototype.constructor = base;

      base.prototype.constructor = base;

      因为否则,原型构造函数

      because otherwise, the prototypes constructor of


      var Top = new base();

      var Top = new base();

      如果原型被设置为Nothing,那么Nothings'或者不会从原型链的某个地方继承构造函数 - >

      would be Nothings' or does'nt base inherit a constructor from somewhere up the prototype chain if the prototype is set to Nothing ->


      顶部instanceof base // false

      Top instanceof base // false



      更新



      我最终做到了以这样的方式现在:

      Update

      I ended up doing it in a way like this now:

      var base = {
      // a tiny little selfmade prototypical inheritance system
      // you are free to add function arguments for extending the created objects
      // neither instanceof nor .constructor is featured, because "classes" are no functions
          create: function(extension,desc) {
              // instances inherit from the proto objects
              var newInst = Object.create(this.proto, desc);
              if(this.proto.childExtendable) //if Subclass allows its Children to be Extendible, do so
                  newInst.extend(extension);
              if(newInst.init||this.proto.init) //4
                  newInst.init()                          
              return newInst
          },
          inherit: function(props) {
              // the "class" inherits static methods from the class
              var sub = Object.create(this);
              // and the proto objects inherits from the parent proto
              sub.proto = Object.create(this.proto);
              props.protect = this.protect;
              if(props.childExtendable)
                  props.extend = this.extend;
              this.extend.call(sub.proto, props);
              return sub;
          }, 
          extend: function (props) {
              for (var prop in props) {
                  var propmatch = prop.match(/(.*?)__(.{1,5}?)__(.*)/)||["",prop,"",""];
                  this[propmatch[1]+propmatch[3]] = props[prop];
                  if(propmatch[2])
                      this.protect(propmatch[1]+propmatch[3],propmatch[2]);           
              }
          },
          protect: function(prop,flags) { //with each call it toggles the given flags,  so you can protect funcitons given to the inherit function ;; //This should be available to all childs, but adding it to the base.proto, it changes Object.prototyppe ( therefore not a good idea)
              var d  = Object.getOwnPropertyDescriptor(this, prop);
              if (flags.match(/w/)){
                   Ti.API.info("Setting writable for propertie " + prop + " in Object " + this + " to " + !d.writable);
                   Object.defineProperty(this, prop, {writable:!d.writable});};
              if (flags.match(/c/)){
                  Ti.API.info("Setting configurable for propertie " + prop + "in Object " + this);
                  Object.defineProperty(this, prop, {configurable:!d.configurable});};
              if (flags.match(/e/)){
                  Ti.API.info("Setting enumerable for propertie " + prop + "in Object " + this);
                  Object.defineProperty(this, prop, {configurable:!d.enumerable});};
              if (flags.match(/a/)){
                  Ti.API.info("Setting enumerable for propertie " + prop + "in Object " + this);
                  Object.preventExtensions(this);};
         },
          init: function() {},
          proto: Object.prototype // or null, if you want
      };
      
      var Human = base.inherit({ //will be put in Human.proto
          childExtendable:true,
          init:function() {alert("Humans Init for all Instances")},
          say:function() { alert("Hi, I'm "+this.name); }
      });
      Human.proto.name = "default"; // You could use an argument to the inherit function
                                    // I just want to make clear what happens
      Ti.API.info(Object.getPrototypeOf(Function) + "a");
      var paul = Human.create({ //extends this object
          name: "Paul",
          test: function() {alert("test")},
          init__wce__: function() {alert("Pauls Own Init")},
          say__w__ : function() { alert("Hi, I'm" + this.name + "s Own Function")}
      });
      paul.name = "Paul";           // and again, the create function might do it for you
      paul.say = function() {alert("Pauls say is overwritten")} // define init without __wce__ and it will be overwritten
      paul.say(); // -> "Hi, I'm Paul"
      

      如果有人关心

      但是, jsfiddle不会运行这个,Titanium会按预期执行每个
      可能是某些严格模式(??)

      Just if anyone cares
      However, jsfiddle won't run this, Titanium does everythign as expected maybe some strict mode (??)

      推荐答案


      Human中给出的方法只在ram中存在一次吗?

      Do the methods given in Human only exist once in the ram?

      是。


      和Human1.walk()指向它?

      and Human1.walk() points to it?

      是。更正确的是, Human1 Human 的原型有一个指向它的属性walk。

      Yes. To be more correct, the prototype of Human1, Human, has a property "walk" pointing to it.


      我想知道这是否是这样做的正确方法?我对JavaScript比较陌生。

      I wonder if this is the right Approach of doing it like this? I'm relatively new to JavaScript.

      我会说不,因为它过于复杂,而且部分错误。

      I'd say no, because it is overly complicated, and partly wrong.


      • Human实例的原型链包括 base 。多数民众多,你需要为每个实例覆盖create和extend方法。通常的方法是classes包含一个prototype属性,其实例继承该属性。

      • 您的模式打破 instanceof 运算符,虽然这可能是一个小问题。

      • extend方法令人困惑。它不会扩展对象本身,而是创建一个从它继承的新对象,并在其上设置属性和属性描述符。更好地实现同样的事情:

      • The prototype chain of Human instances includes base. Thats odd, and you need to overwrite the create and extend methods for every instance. The usual method is that "classes" contain a "prototype" property, from which their instances inherit.
      • Your pattern breaks the instanceof operator, although that might be a minor issue.
      • The extend method is confusing. It does not extend the object itself, but create a new object inheriting from it and setting properties and property descriptors on that. Better implementation of the same thing:

      base.inherit = function(descs, props) {
          // creates a new object inheriting from this
          var that = Object.create(this, descs); // will even work when undefined
          if (props)
              for (var prop in props)
                  that[prop] = props[prop];
          // Object.freeze(that);       
          return that;
      };
      






      扩展问题:


      To the extended question:

      base.prototype = Nothing​;
      base.constructor = base;
      

      没用。首先,默认情况下,任何函数的prototype属性都是(几乎)空对象,直到您覆盖它为止。无需将其设置为 nothing : - )

      is quite useless. First, the "prototype" property of any function is an (nearly) empty object by default, until you overwrite it. No need to set it to nothing :-)

      构造函数属性通常是原型属性。它将由所有实例继承,指向thei构造函数。您只需要在覆盖函数的prototype属性时明确设置它 - 并且您不应该在函数本身上设置构造函数属性。

      And the "constructor" property is usually a prototype property. It would be inherited by all instances, pointing to thei constructor function. You only need to set it explicitly when overwriting a function's "prototype" property - and you should not set the the "constructor" property on the function itself.

      (继续: )我更多关于这样的解决方案:

      (continuing:) I though more about a solution like this:

      var base = {
      // a tiny little selfmade prototypical inheritance system
      // you are free to add function arguments for extending the created objects
      // neither instanceof nor .constructor is featured, because "classes" are no functions
          create: function([desc]) {
              // instances inherit from the proto objects
              return Object.create(this.proto, [desc]);
          },
          inherit: function([props]) {
              // the "class" inherits static methods from the class
              var sub = Object.create(this);
              // and the proto objects inherits from the parent proto
              sub.proto = Object.create(this.proto);
              [Object.extend(sub.proto, props);]
              return sub;
          },
          proto: Object.prototype // or null, if you want
      };
      
      var Human = base.inherit();
      Human.proto.name = "default"; // You could use an argument to the inherit function
                                    // I just want to make clear what happens
      Human.proto.say = function() { alert("Hi, I'm "+this.name); };
      
      var paul = Human.create();
      paul.name = "Paul";           // and again, the create function might do it for you
      paul.say(); // -> "Hi, I'm Paul"
      

      这样, paul 继承自 Human.proto 继承自 base.proto ,即对象。原型 null 。并且 Human 继承自 base ,即您可以使用 Human轻松构建子类。 inherit()

      This way, paul inherits from Human.proto inherits from base.proto which is Object.prototype or null. And Human inherits from base, i.e. you could easily build a "subclass" with Human.inherit().

      您是否想要使用属性描述符绝对是您的选择。您可以使用 Object.defineProperties (或 Object.create 的第二个参数)随处创建并扩展它。以及 Object.extend (通常的for-in-copy-method)。

      Whether you want to use property descriptors or not is absolutely your choice. Everywhere you create something and extend it, you might use Object.defineProperties (or the second argument to Object.create) as well as Object.extend (the usual for-in-copy-method).


      使用Object.create()从Objects继承和设置原型和构造函数有什么主要好处?

      what are the main benefits from using Object.create() to inherit from Objects vs Setting the prototypes and construcotrs?

      它是一个设计选择。 Object.create 不会在构建对象上调用[constructor]函数。请参阅使用Object.create。而不是新了解Object.create()与新SomeFunction()之间的区别更多信息。

      It's a design choice. Object.create won't call a [constructor] function on the built object. See Using "Object.create" instead of "new" or Understanding the difference between Object.create() and new SomeFunction() for further information.


      base.prototype = {}; 不会阻止这样做原型链直到Object.prototype?

      base.prototype = {}; doesnt prevent s.o to go up the prototype chain til Object.prototype?

      是的。一个空对象(由您的文字创建)在其链中仍然具有 Object.prototype 。唯一的方法是 Object.create(null)(不能用 new 进行填充)。

      Yes. An empty object (as created by your literal) still has Object.prototype in its chain. The only way to do this is Object.create(null) (not shim-able with new).


      我认为我必须设置 base.prototype.constructor = base;

      不是这种情况。拥有函数base(){...} ,将其prototype属性设置为 {constructor:base} 绝对没有任何改变(除了现在在枚举中的构造函数) - 每个函数都有这样一个默认的proto对象,包括构造函数。

      Not in this case. Having a function base(){...}, setting its "prototype" property to {constructor: base} changes absolutely nothing (except that "constructor" in enumerable now) - every function has such a default proto object including the "constructor".

      所以只有当你需要覆盖时带有新对象的prototype属性,当它让它继承自另一个函数的原型时,你可以添加这个方便属性: MySubClass.prototype = Object.create(MyClass.prototype,{constructor: {value:MySubClass}});

      So only when you need to overwrite the "prototype" property with a new object, as it happens when letting it inherit from another function's prototype, you might add this convenience property: MySubClass.prototype = Object.create(MyClass.prototype, {constructor:{value:MySubClass}});


      否则......

      otherwise...

      什么都不会发生。没有语言功能(例如 instanceof )需要原型对象上的构造函数属性,并且很少使用。没有什么能打破。

      Nothing would happen. The "constructor" property on prototype objects is needed for no language features (like instanceof), and is seldom used. It's likely that nothing breaks.

      这篇关于Object.create原型链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆