javascript - 有关对象中属性存储位置的几个问题

标签 javascript

I asked earlier即使我做了类似的事情,为什么ribs.js的_.isArray(arr)函数仍然返回true,

var a = [];
    a.something = "test";


因为我有点期望它会变成一个[object Object](不确定这是否是引用var o = {}时引用的对象的正确方法,但是我是在谈论可以使用的对象类型关键:价值配对,任何有关如何引用该对象的见解都将受到欢迎。

我收到的答案是,它不会更改a的数据类型,而只是向其中添加属性something。我可以在控制台中看到我得到a.something =“ test”,但这存储在哪里?它在数组的原型中吗? (我很确定不是)。但是,简单地“添加属性”是什么意思?

var a = "";
a.asdf = "test";
a.zxcv = "test1";


不会以类似的方式返回属性,因为字符串不是对象,但是函数应该是对象

var a = function(){};

    a.asdf = "test";
    a.zxcv = "test1";

    console.log(a);


只返回

function (){

} 


(它看起来像一个字符串...)我不知道为什么我不能做var a = new Function()(即使我以前从未见过)。它返回与上面直接相同的结果。 jslint也说这是对的。为什么..?

我只是想弄清楚“向对象添加属性”的含义,以及这些属性“去”的地方,以及为什么它们在不同类型的对象中的行为不同

最佳答案

在JavaScript中,有几种原始类型,包括undefinednumberstring。也有object。所有对象都有属性。

每个小写字母-o的对象都是从构造函数创建的。对于对象文字表示法,构造函数为隐式Object。数组也是对象,但不是使用Object构造函数创建的,而是使用Array构造函数创建的。函数也是对象,具有Function构造函数。

数组

当您看到一个数组时,您可能会认为它具有编号的元素。 0、1、2等。实际上,数组只是另一个对象,除了不使用字母属性名称,它使用数字属性名称,而且您不使用.访问元素。

实际上,数组通过浏览器进行了一些优化,以使其比使用其他类型的对象时更快,但是此类优化仍将保留此处描述的语义。

拳击

字符串的奇怪行为是因为字符串不是对象,但是有些古怪的拳击行为使someString.property = value不再是错误。只有对象本身才能具有属性和方法。但是我们都知道someNumber.toString()不是错误。那里怎么了?

事实证明,在某些情况下,当您尝试将原语当作对象使用时,会将原语装箱成一个对象。例如,当我调用someNumber.toString()时,它将使用Number构造函数创建一个对象,该对象与原始编号不同。然后,它以常规方式查找toString,并在this设置为对象的情况下执行它。

在字符串上设置属性时,出于该操作的目的,该属性被隐式转换为String -constructor对象。它将String对象的属性设置得很好。只是拳击是暂时的;装箱不会保留在包含原始字符串的变量中。

功能对象

的确,我们很少使用new Function,但是,如果您确实使用它,它确实可以像它听起来那样:它创建了一个新函数。您可以向它传递一个字符串,它将成为函数的主体。如果您创建一个带有字符串主体的新函数,然后调用它,则与eval ing代码相距不远。这就是JSLint将其标记为eval的原因。

当您将对象记录到控制台时,开发人员工具通常会向您显示属性,因为这通常是对象最重要的部分。通常,不会为函数分配自定义属性,因此开发人员工具仅使用纯字符串表示形式,该字符串通常仅显示函数参数和主体。函数的字符串表示形式在不显示属性的情况下并不常见-普通toStringObject仅返回[object Object]

原型链

当然,这些信息可以澄清很多事情,但是仍然不能解释这一点:

console.log(new Array() instanceof Object);  // => true


ha?数组的构造函数是Array,而不是Object!这是由于所谓的原型链。它是控制继承的方法。

每个对象都有一个称为[[Prototype]]的内部属性。尽管许多浏览器都具有非标准的__proto__属性来访问它,但是没有标准的方法来访问它。使用new创建对象时,会将[[Prototype]]设置为用于创建对象的函数的prototype属性。

假设我们有一个对象foo,它的构造函数是Foo。当我们访问属性foo.bar时,它首先在bar自己的属性中查找foo。如果在此处找不到或未定义它,它将在barfoo自身属性中查找[[Prototype]]。如果没有找到,它将不停地在barfoo[[Prototype]]中查找[[Prototype]],直到到达null [[Prototype]]。这是允许继承的功能。

为了确定对象是否是实例,isinstance遍历了原型链,以查看任何[[Prototype]]是否与函数的prototype匹配。事实证明,如果遍历数组的原型链,则会遇到Array的原型,Object的原型,然后是null。因此,isinstance将在true中产生new Array() instanceof Object

进一步阅读

您可能对annotated ECMAScript 5 specification感兴趣,它定义了语言,并且当然涵盖了详细使用的某些特定算法。它不会为您布置一切;一些非常有见地的事情没有明确描述,但是需要自己拼凑几位。因此,除非您自己尝试实施,否则可能不希望直接阅读它,而只要您对某些行为感到好奇,就应该参考它的各个部分。

关于javascript - 有关对象中属性存储位置的几个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17849537/

相关文章:

javascript - 使用滚动事件显示基于窗口高度的元素

javascript - 即使阈值高于 HighStock 中的最大 y 轴值,也显示阈值线

javascript - Angular 6 错误 "NullInjectorError: No provider for Router!"

javascript - JSTREE、dnd - 通过拖放更新 SQL 数据库

javascript - 在 JavaScript 的字符串输出中应用条件语句

javascript - 在 Python 中,您可以像在 JavaScript 中那样对字符串函数进行原型(prototype)设计吗?

javascript - 当 iOS 低功耗模式处于事件状态时如何播放 html 视频?

带有 setInterval 的 JavaScript 计时器不起作用?

javascript - After Effects 作为后端电影引擎?

javascript - 下行链接更改为滚动时返回顶部链接