好的,旋风之旅:
对象
对象是具有属性的事物。属性具有名称和值。名称始终是字符串(尽管大多数时候我们可以不带引号将它们写成),值可以是 JavaScript 支持的任何内容:数字、字符串、布尔值、null、未定义或对对象的引用。
所以:
var a = {
propertyName: "property value"
};
a是一个引用对象的变量,该对象有一个名为propertyName的属性,其值为字符串"property value"。
原型
一个对象(比如,obj)可以有另一个对象(比如,p)“在”它后面,p 借给obj 的属性,除非obj 有自己的属性和给定的名称. p 是 obj 的 prototype 对象。举个例子最容易理解:
// Let's create an object `p` with a couple of properties, `x` and `y`
// This syntax is called an "object initializer" (aka "object literal")
var p = {
x: "x on p",
y: "y on p"
};
// Now, we'll create a new object, `obj`, using `p` as its prototype
var obj = Object.create(p);
// And that means if we ask `obj` for a property called `x`, since it doesn't
// have its **own** `x`, it asks `p` for it. (And the same with `y`)
console.log(obj.x); // "x on p"
console.log(obj.y); // "y on p"
// But we can give `obj` its *own* `x` instead if we want
obj.x = "x on obj";
console.log(obj.x); // "x on obj"
console.log(obj.y); // "y on p"
// Doing that to `obj` had no effect on `p`
console.log(p.x); // "x on p"
console.log(p.y); // "y on p"
原型的一个非常非常重要的方面是对象之间的连接是实时的。因此,如果obj 没有y 属性,则每次我们向obj 询问y 时,它都会询问p。因此,如果我们将p 的值更改为y,如果我们向obj 询问,该更改就会出现:
var p = {
x: "x on p",
y: "y on p"
};
var obj = Object.create(p);
console.log(obj.y); // "y on p"
p.y = "updated y on p";
console.log(obj.y); // "updated y on p"
这种实时连接是至关重要的。再说一遍,这样想:我们询问 obj 获取属性y,而obj 说“我没有自己的,所以我会去问@987654349 @ 给它,然后给你。”
注意:我用来创建 obj 的 Object.create 函数是 ECMAScript5 的新功能(几年前的规范更新)。我们将回到另一种方式来为对象提供更进一步的原型。
对象的原型目前始终在创建对象时设置,并且无法更改(在创建obj 后,我无法在上面的q 中替换p)。上面我使用Object.create 来完成它(下面我们将讨论构造函数)。在 ECMAScript5 (ES5) 之前,没有标准的方法来获取对象的原型。 ES5 现在为我们提供了一种方法,称为Object.getPrototypeOf,但仍然没有提供改变它的方法。下一个版本 ES6 会更进一步。
功能
函数是执行操作的代码单元。函数也是对象,因此它们可以具有属性,尽管实际上在函数上使用属性相对较少(call 和 apply 除外,我们无需在这里讨论)。
你可以声明一个函数:
function foo() {
}
...或者您可以使用 表达式创建一个:
// An anonymous -- unnamed -- function assigned to variable `foo`
var foo = function() {
};
// A function named `f` assigned to variable `foo`
var foo = function f() {
};
声明和表达方式不同。在执行同一范围内的任何分步代码之前,对函数声明进行评估。与所有其他表达式一样,函数表达式在分步代码中遇到时进行评估。 (人们有时称其为“提升”,因为这意味着实际上,即使函数声明位于作用域的底部,它也会像被提升——提升——到顶部一样发生。)
函数可以有参数:
// `a` and `b` are arguments
function sum(a, b) {
console.log(a + b);
}
它们可以有返回值:
function sum(a, b) {
return a + b;
}
console.log(sum(1, 2)); // "3"
如果函数没有返回其他值,则调用该函数的结果是值undefined。
方法
JavaScript 没有方法。它只有功能——但这就是它真正需要的。但是如果你有一个分配给对象属性的函数,并且你调用该函数作为从对象中检索属性的表达式的一部分,那么就会发生一些事情使得 JavaScript 似乎 有方法:@987654364 @ 关键字指的是函数调用中的那个对象。再一次,一个例子创造了奇迹:
// A blank object
var obj = {};
// Lets put a function on it as a property
obj.foo = function() {
console.log("this is obj? " + this === obj);
};
// Let's call that function
obj.foo(); // "this is obj? true"
更多关于我的博客:
构造函数
构造函数与new 关键字一起使用,它们是为对象提供原型的方法之一。当您通过new 调用函数时,会创建一个新对象,并从函数的prototype 属性中分配一个原型:
function Foo() {
}
Foo.prototype.x = "x on Foo.prototype";
var obj = new Foo();
console.log(obj.x); // "x on Foo.prototype"
每个函数都会自动拥有一个prototype 属性,尽管我们当然不会将绝大多数函数用作构造函数。
这里需要注意的重要一点:函数的prototype 属性只是一个无聊的旧属性。它不是任何对象的原型,除非/除非通过 new 运算符调用该函数。当您通过new 调用函数时,new 运算符使用函数的prototype 属性来设置新对象的原型,但仅此而已。
值得一提的是,在 ES5 之前,像上面这样的构造函数是您可以使用给定原型创建对象的唯一方法。但是在 ES5 中,我们得到了Object.create,它为如何使用 JavaScript 开辟了更多的模式。 (通过使用临时函数总是可以创建自己的Object.create,事实上这正是某些人所做的。)有些人不喜欢使用new 关键字和prototype 属性,他们更喜欢使用“构建器”模式,您只需调用一个函数并取回一个对象。 JavaScript 非常灵活,您可以做到这一点。
更多探索