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。为什么..?
我只想弄清楚“向对象添加属性”是什么意思,以及这些属性“去”的地方,以及为什么它们在不同类型的对象中的行为方式不同
答案 0 :(得分:3)
在JavaScript中,有几种原始类型,包括undefined
,number
和string
。还有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中使用类的方法。