关于属性存储在对象中的几个问题

时间:2013-07-25 05:13:49

标签: javascript

I asked earlier为什么backbone.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也说它是eval。为什么..?

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

2 个答案:

答案 0 :(得分:3)

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

每个小写o对象都是从构造函数创建的。在对象文字表示法的情况下,构造函数是隐式Object。数组也是对象,但不是使用Object构造函数创建的,而是使用Array构造函数创建的。函数也是对象,它们具有Function构造函数。

阵列

当你看到一个数组时,你可能会认为它有编号元素;实际上,数组只是另一个对象,除了使用数字属性名称而不使用字母属性名称,并且不使用.来访问元素。 / p>

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

拳击

字符串的奇怪行为是因为字符串不是对象,但是有一些古怪的拳击行为使得someString.property = value不是错误。只有对象本身可以拥有属性和方法;但我们都知道someNumber.toString()不是错误。那里有什么?

事实证明,在某些情况下,当您尝试使用原语时,就好像它是一个对象一样,它会将该原语打包成一个对象。例如,当我调用someNumber.toString()时,它将创建一个具有Number构造函数的对象,与原始数字不同。然后它以正常方式查找toString,并在设置为对象的this的情况下执行它。

当您在字符串上设置属性时,它会隐式转换为String - 构造函数对象,以用于该操作。它在String对象上设置属性就好了;这只是拳击是暂时的;拳击不会持有保存原始字符串的变量。

功能对象

确实,我们很少使用new Function,但是如果你确实使用它,它会完全像它听起来那样:它创建一个新函数。你可以传递一个字符串,这将是函数的主体。如果你创建一个带有字符串主体的新函数然后调用它,那就离eval代码不太远了。这就是为什么JSLint将其标记为eval

将对象记录到控制台时,开发人员工具通常会显示属性,因为这通常是对象中最重要的部分。函数通常不会分配自定义属性,因此开发人员工具只使用普通字符串表示,通常只显示函数参数和正文。函数的字符串表示在不显示属性时并不常见 - 普通toString的{​​{1}}将只返回Object

原型链

当然,这些信息澄清了许多事情,但它仍然无法解释这一点:

[object Object]

什?数组的构造函数是console.log(new Array() instanceof Object); // => true ,而不是Array!这是因为称为原型链的东西。这是控制继承的原因。

每个对象都有一个名为Object的内部属性。虽然许多浏览器都有非标准的[[Prototype]]属性来访问它,但没有标准的方法来访问它。使用__proto__创建对象时,new设置为用于创建对象的函数的[[Prototype]]属性。

假设我们有一个对象prototype,其构造函数为foo。当我们访问属性Foo时,它会首先在foo.bar自己的属性中查找bar。如果在那里找不到或未定义,它将在foo的{​​{1}}自己的属性中查找bar。如果在那里找不到,它会在foo的{​​{1}} [[Prototype]] bar中依次查找foo,直到它变为[[Prototype]] { {1}}。这是允许继承的功能。

为了确定一个对象是否是一个实例,[[Prototype]]遍历原型链,看看是否有null个匹配函数的[[Prototype]]。事实证明,如果你遍历一个数组的原型链,你将会点击isinstance的原型,[[Prototype]]的原型,然后prototype。因此,Array会在Object中产生null

进一步阅读

您可能对定义语言的annotated ECMAScript 5 specification感兴趣,当然也会详细介绍一些特定的算法。它不会为你奠定一切;一些非常有见地的事情没有明确描述,但需要自己拼凑几个位。出于这个原因,你可能不想直接阅读它,除非你试图自己实现它,而是在你有一些好奇的行为时引用它的部分。

答案 1 :(得分:0)

在javascript中,数组只是一个对象,具有从0到n个值的预分配键。

var x = ['a','b','c','d',234];

完全相同

var x = {0:'a',1:'b',2:'c',3:'d',4:234,length:5};所有数组函数都可以使用像Array.prototype.sort.push(x,'sdfsd');这样的数组调用。

主对象的所有方法/属性都由所有数组继承。

因此,当您为数组指定非数值时,请假设有2个元素。它会像这样添加......

var x =['a','Stack','flow',0];
--added value x.a = 'something';
it really looks like this now
var x = {
    0:'a',
    1:'Stack',
    2:'flow',
    3:'0',
    a:'something'
    }

然而,对于js x 仍然是一个数组,当您在 x 上运行任何函数时, a 将不会显示。直到您像x.a一样访问它。

x.hasOwnProperty('a'); //true

Object.keys(x); //listing all keys in object(array x)
// ["0", "1", "2", "3", "a"] !!!keys function returns an array consisting of all keys in an object.

功能对象不同,它们不仅仅是带键的对象。

你仍然可以为他们分配东西,但他们只会返回功能。您可以访问x.a等属性。但不要这样做。

<强>摘要

所有内容都继承自Object对象,因此可以拥有属性和方法。

数组是专用对象,称为Array,它继承Object中的方法/道具,它将值存储在名为0-n form的索引键中。但是由于继承,再次可以有额外的属性和方法,尽管不会出现在数组方法或属性中。

函数是继承自function object的{​​{1}}继承的对象,因此函数(functionObjects)具有两者的属性。函数具有额外的属性,就像原型和参数一样。

当你写这个:...

Object 发生了三件事:  1. x = {};  2.函数执行...如果它有this.p = etcc ...则x得到它而x变为x = {p:'etc'}  3. x。 proto = function.prototype

然后如果你在x中查找属性或方法并且没有找到,那么js将会查看proto中是否存在某些内容,它指的是函数的原型对象,然后在那里进行搜索。这就是你在Javascript中使用类的方法。