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中,有几种原始类型,包括undefined
,number
和string
。也有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
的原因。
当您将对象记录到控制台时,开发人员工具通常会向您显示属性,因为这通常是对象最重要的部分。通常,不会为函数分配自定义属性,因此开发人员工具仅使用纯字符串表示形式,该字符串通常仅显示函数参数和主体。函数的字符串表示形式在不显示属性的情况下并不常见-普通toString
的Object
仅返回[object Object]
。
原型链
当然,这些信息可以澄清很多事情,但是仍然不能解释这一点:
console.log(new Array() instanceof Object); // => true
ha?数组的构造函数是
Array
,而不是Object
!这是由于所谓的原型链。它是控制继承的方法。每个对象都有一个称为
[[Prototype]]
的内部属性。尽管许多浏览器都具有非标准的__proto__
属性来访问它,但是没有标准的方法来访问它。使用new
创建对象时,会将[[Prototype]]
设置为用于创建对象的函数的prototype
属性。假设我们有一个对象
foo
,它的构造函数是Foo
。当我们访问属性foo.bar
时,它首先在bar
自己的属性中查找foo
。如果在此处找不到或未定义它,它将在bar
的foo
自身属性中查找[[Prototype]]
。如果没有找到,它将不停地在bar
的foo
的[[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/