草庐IT

JavaScript 继承和构造函数属性

coder 2023-07-05 原文

考虑以下代码。

function a() {}
function b() {}
function c() {}

b.prototype = new a();
c.prototype = new b();

console.log((new a()).constructor); //a()
console.log((new b()).constructor); //a()
console.log((new c()).constructor); //a()
  • 为什么不为 b 和 c 更新构造函数?
  • 我做错了继承吗?
  • 更新构造函数的最佳方法是什么?

  • 此外,请考虑以下事项。
    console.log(new a() instanceof a); //true
    console.log(new b() instanceof b); //true
    console.log(new c() instanceof c); //true
    
  • 鉴于 (new c()).constructor等于 a()Object.getPrototypeOf(new c())a{ } , instanceof 怎么可能要知道new c()c 的一个实例?

  • http://jsfiddle.net/ezZr5/

    最佳答案

    好吧,让我们来玩一个小游戏:



    从上图我们可以看出:

  • 当我们创建像 function Foo() {} 这样的函数时, JavaScript 创建一个 Function实例。
  • Function实例(构造函数)有一个属性 prototype这是一个指针。
  • prototype构造函数的属性指向它的原型(prototype)对象。
  • 原型(prototype)对象有一个属性 constructor这也是一个指针。
  • constructor原型(prototype)对象的属性指向其构造函数。
  • 当我们创建 Foo 的新实例时喜欢 new Foo() , JavaScript 创建一个新对象。
  • 内部[[proto]]实例的属性指向构造函数的原型(prototype)。

  • 现在,问题出现了,为什么 JavaScript 不附加 constructor属性到实例对象而不是原型(prototype)。考虑:
    function defclass(prototype) {
        var constructor = prototype.constructor;
        constructor.prototype = prototype;
        return constructor;
    }
    
    var Square = defclass({
        constructor: function (side) {
            this.side = side;
        },
        area: function () {
            return this.side * this.side;
        }
    });
    
    var square = new Square(10);
    
    alert(square.area()); // 100
    

    如您所见 constructor property 只是原型(prototype)的另一种方法,如 area在上面的例子中。是什么让 constructor属性的特殊之处在于它用于初始化原型(prototype)的一个实例。否则它与原型(prototype)的任何其他方法完全相同。

    定义 constructor由于以下原因,原型(prototype)上的属性是有利的:
  • 这在逻辑上是正确的。例如考虑 Object.prototype . constructor Object.prototype 的属性(property)指向 Object .如果 constructor属性是在实例上定义的,然后 Object.prototype.constructor将是 undefined因为Object.prototypenull 的一个实例.
  • 它的处理方式与其他原型(prototype)方法没有区别。这使得 new 的工作更容易,因为它不需要定义 constructor每个实例的属性。
  • 每个实例共享相同的 constructor属性(property)。因此它是有效的。

  • 现在当我们谈论继承时,我们有以下场景:



    从上图我们可以看出:
  • 派生构造函数的 prototype属性设置为基本构造函数的实例。
  • 因此内部 [[proto]]派生构造函数实例的属性也指向它。
  • 因此 constructor派生构造函数实例的属性现在指向基构造函数。

  • 至于instanceof运算符,与流行的看法相反,它不依赖于 constructor实例的属性。从上面我们可以看到,这会导致错误的结果。
    instanceof运算符是二元运算符(它有两个操作数)。它对实例对象和构造函数进行操作。正如 Mozilla Developer Network 上的解释,它只是执行以下操作:
    function instanceOf(object, constructor) {
        while (object != null) {
            if (object == constructor.prototype) { //object is instanceof constructor
                return true;
            } else if (typeof object == 'xml') { //workaround for XML objects
                return constructor.prototype == XML.prototype;
            }
            object = object.__proto__; //traverse the prototype chain
        }
        return false; //object is not instanceof constructor
    }
    

    简单地说,如果Foo继承自 Bar ,然后是 Foo 实例的原型(prototype)链将会:
  • foo.__proto__ === Foo.prototype
  • foo.__proto__.__proto__ === Bar.prototype
  • foo.__proto__.__proto__.__proto__ === Object.prototype
  • foo.__proto__.__proto__.__proto__.__proto__ === null

  • 如您所见,每个对象都继承自 Object构造函数。原型(prototype)链在内部 [[proto]] 结束时结束。属性指向 null .
    instanceof函数简单地遍历实例对象的原型(prototype)链(第一个操作数)并比较内部[[proto]]每个对象的属性到 prototype构造函数的属性(第二个操作数)。如果它们匹配,则返回 true ;否则,如果原型(prototype)链结束,则返回 false .

    关于JavaScript 继承和构造函数属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8093057/

    有关JavaScript 继承和构造函数属性的更多相关文章

    1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

      我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

    2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

      我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

    3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

      我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

    4. ruby - 多个属性的 update_column 方法 - 2

      我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

    5. ruby - Nokogiri 剥离所有属性 - 2

      我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

    6. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

      我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

    7. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

      对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

    8. ruby - 在 Ruby 中有条件地定义函数 - 2

      我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

    9. ruby - 在 Ruby 中按名称传递函数 - 2

      如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

    10. ruby-on-rails - Rails 单表继承 : How to override the value written to the type field - 2

      在我的系统中,我已经定义了STI。Dog继承自Animal,在animals表中有一个type列,其值为"Dog"。现在我想让SpecialDog继承自dog,只是为了在某些特殊情况下稍微修改一下行为。数据还是一样。我需要通过SpecialDog运行的所有查询,以返回数据库中类型为Dog的值。我的问题是因为我有一个type列,rails将WHERE"animals"."type"IN('SpecialDog')附加到我的查询中,所以我不能获取原始的Dog条目。所以我想要的是以某种方式覆盖rails在通过SpecialDog访问数据库时使用的值,使其表现得像Dog。有没有办法覆盖用于类型

    随机推荐