gpt4 book ai didi

javascript - 原型(prototype)还是内联,有什么区别?

转载 作者:行者123 更新时间:2023-12-02 23:37:46 25 4
gpt4 key购买 nike

我只是在学习Javascript,我想知道正在使用原型(prototype)声明,如下所示:

function TSomeObj()
{
this.name="my object";
}

TSomeObj.prototype.showname = function() {
alert(this.name);
}

基本上和这样做是一样的:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}

当我转储对象的属性时,会得到相同的结果:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}

TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}

使用原型(prototype)声明的确切好处是什么?除了更少的困惑和更有条理的源代码之外。

更新:我也许应该更清楚地表明这是我很好奇的最终结果。最终结果当然是相同的(即都在对象原型(prototype)中注册了一个新函数),但是它们的执行方式却截然不同。感谢您的所有答复和信息!

最佳答案

我最初回答了错误的问题。这是您实际提出的问题的答案。我会留下其他笔记,以防它们对某人有帮助。

通过this.prop向构造函数中的对象添加属性与通过Object.prototype.prop在外部添加属性不同。

  • 最重要的区别是,当您向函数原型(prototype)中添加属性并从中实例化一个新对象时,通过加强继承链而不是直接将其放在对象上,可以在新对象中访问该属性。
    var baseobj = {};
    function ObjType1() {
    this.prop = 2;
    }
    function ObjType2() {}
    ObjType1.prototype = baseobj;
    ObjType2.prototype = baseobj; // these now have the *same* prototype object.
    ObjType1.prototype.prop = 1;
    // identical to `baseobj.prop = 1` -- we're modifying the prototype

    var a = new ObjType1(),
    b = new ObjType2();
    //a.hasOwnProperty('prop') : true
    //b.hasOwnProperty('prop') : false -- it has no local property "prop"
    //a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain

    baseobj.prop = 3;
    //b's value changed because we changed the prototype
    //a: { prop = 2 }, b : { prop = 3 }

    delete a.prop;
    //a is now reflecting the prototype's "prop" instead of its own:
    //a: { prop = 3 }, b : { prop = 3 }
  • 第二个区别是,在代码执行时,向原型(prototype)添加属性一次,但是每次创建新对象时,都向构造函数内部的对象添加属性。这意味着使用原型(prototype)的性能更好,并且使用的内存更少,因为在您对叶子/邻近对象设置相同属性之前,不需要任何新存储。
  • 另一个不同之处在于,内部添加的函数可以访问私有(private)变量和函数(在构造函数中使用var声明的变量),而基于原型(prototype)的函数或外部添加的函数则不能访问,仅仅是因为它们的作用域不正确:
    function Obj(initialx, initialy) {
    var x = initialx,
    y = initialy;
    this.getX = function() {
    return x;
    }
    var twoX = function() { // identical to `function twoX() { ... }`
    return x * 2;
    }
    this.getTwoX = function() {
    return twoX();
    }
    }

    Obj.prototype.getY = function() {
    return y; // fails, even if you try `this.y`
    }
    Obj.prototype.twoY = function() {
    return y * 2; // fails
    }
    Obj.prototype.getTwoY = function() {
    return twoY(); // fails
    }

    var obj = new Obj();
    // obj.y : fails, you can't access "y", it is internal
    // obj.twoX() : fails, you can't access "twoX", it is internal
    // obj.getTwoX() : works, it is "public" but has access to the twoX function

  • 关于javascript对象,函数和继承的一般说明
  • javascript中的所有非标量变量都是对象。 (当对它们使用某种方法时,某些明显的非对象类型会进行装箱,例如 bool(boolean) 值)。它们的行为有点像哈希/字典,因为它们可以分配给它们无限数量的键/值对。
  • 每个对象都有一个“原型(prototype)”的继承链,一直到基础对象。当您访问对象的属性时,如果该对象本身不存在该属性,则将检查该对象的 secret 原型(prototype),如果不存在,则将检查该对象的原型(prototype),依此类推。一些浏览器通过属性__proto__公开此原型(prototype)。常规对象没有prototype属性,因为该属性用于函数,用于存储将使用该函数作为其构造函数创建的任何新对象的原型(prototype)的对象。
  • javascript函数是对象的一种特殊情况,它除了具有对象的键/值对外,还具有按顺序执行的参数和一系列语句。
  • 每次调用一个函数对象时,它都会与另一个对象配对,该对象可以通过关键字this从函数内部进行访问。通常,this对象是该函数所属的对象。例如,''.replace()将字符串文字包装到String,然后在replace函数内部,该字符串指向该对象。另一个示例是将函数附加到DOM元素(可能是按钮上的onclick函数)时,this引用DOM元素。您可以使用thisapply动态地手动选择配对的call对象。
  • 当像new中那样使用var obj = new Obj()关键字调用javascript函数时,这会导致发生特殊情况。如果您没有专门返回任何内容,则它现在包含在调用时与该函数配对的this对象,而不是现在包含obj函数的返回值的Obj,它将是一个新的空对象,其中第一个父对象位于其继承链设置为Obj.prototype(请记住,在某些浏览器中可以通过obj.__proto__访问)。在运行时,调用的Obj()函数可以修改新对象的属性。然后返回该对象。
  • 您不必担心关键字constructor,只需要说obj.constructor指向Obj函数即可(因此您可以找到创建它的东西),但是您可能不需要在大多数情况下使用它东西。

  • 回到您的问题。要了解从构造函数内部修改对象的属性与修改其原型(prototype)之间的区别,请尝试以下操作:
    var baseobj = {prop1: 'x'};
    function TSomeObj() {
    this.prop2 = 'y';
    };
    TSomeObj.prototype = baseobj;
    var a = new TSomeObj();
    //now dump the properties of `a`
    a.prop1 = 'z';
    baseobj.prop1 = 'w';
    baseobj.prop2 = 'q';
    //dump properties of `a` again
    delete a.prop1;
    //dump properties of `a` again

    您会看到,设置 a.prop1实际上是在创建邻近对象的新属性,但它不会覆盖基础对象的prop1。当您从 prop1中删除 a时,您将获得我们更改的继承的 prop1。同样,即使我们在创建 prop2之后添加了 a,但 a仍然具有该属性。这是因为javascript使用原型(prototype)继承而不是经典继承。当您修改 TSomeObj的原型(prototype)时,您还修改了其所有先前实例化的对象,因为它们正在主动从其继承。

    当您以任何编程语言实例化一个类时,新对象都将具有其“构造函数”类的属性(我们通常将其视为该对象的同义词)。而且在大多数编程语言中,除非停止程序并更改类声明,否则不能更改类或实例化对象的属性或方法。

    但是,Javascript允许您在运行时修改对象和“类”的属性,并且该类型类的所有实例化对象也将被修改,除非它们具有覆盖修改的自己的属性。对象可以生出可以生出对象的对象,因此这一直到Object类都在链中起作用。我将“类”用引号引起来,因为实际上,Javascript中的所有内容都是一个对象,实际上没有类之类的东西,只是 new关键字允许您使用继承链为您创建新对象,因此我们即使它们只是用 new关键字调用的构造函数的结果,也可以将它们称为类。

    其他一些注意事项:函数具有Function构造函数,对象具有Object构造函数。 Function构造函数的原型(prototype)是(惊讶,惊讶)Object。

    从对象继承而无需构造函数运行

    在某些情况下,能够在不运行构造函数的情况下创建新的“对象实例”很有用。您可以从类继承而无需运行类的构造函数(就像手动执行 child.__proto__ = parent一样):
    function inheritFrom(Class) {
    function F() {};
    F.prototype = Class.prototype;
    return new F();
    }

    关于javascript - 原型(prototype)还是内联,有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6163186/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com