Layer 1: Single Objects
Layer 1: 单一对象
粗略的说, 在javascript中所有对象都是maps的键值对. 键值对的实体在对象中称为属性( property).属性的key经常为 string类型,而他的value则可以是任何类型包括函数(function). 方法也可以作为函数的值充当属性.
属性的种类(Kinds of Properties)
3种属性的种类:
- 数据属性(Properties or named data properties)
- javascript对象中的常见的属性键值对(mappings from string keys to values). 数据属性包含方法. 这也是最常见的属性.
- 存取器属性 (Accessors or named accessor properties)
- 当用到读,写属性的时候会用到特殊的方法. 一般的属性会在本地存储原型的值;存取器允许你计算属性的值. 你可以将这些属性虚拟化. 关于存取器的详情见 Accessors (Getters and Setters) .
- 内部属性
- 只在 ECMAScript规格说明书中有详细的描述. 从 JavaScript不能直接访问,但是可以间接地访问他们. 规格说明书规定内部属性的 keys在括号中. 例如,
[[Prototype]]
持有对象属性并且通过Object.getPrototypeOf()可以读到此对象的属性值
.
对象的‘字面值’(Object Literals)
JavaScript的对象允许你直接通过赋值的方式创建简单的对象(direct instances of Object。原因是Object的接口
). 下面的代码表示通过对变量 jane赋值,将一个变量转换为对象
. 对象有两个属性:name
和 describe
. describe
是一个方法:
var
jane
=
{
name
:
'Jane'
,
describe
:
function
()
{
return
'Person named '
+
this
.
name
;
// (1)
},
// (2)
};
- 在这个方法中通过
this引用当前对象
(also called the receiver of a method invocation). - ECMAScript 5 允许在对象的属性值末尾有个小逗号(注意:这里说的是最后一个属性的后面) . 哎, 但是不是所有的浏览器都支持. 这个小逗号是很有用的, 因为你可以从新排列你的属性而且不担心他是不是最后一个属性.
你可以通过键值对的映射得到你想要的对象效果. 且他们一般都是设置好的有目的性的对象. 例如, 你可以在对象之间使用继承 (see Layer 2: The Prototype Relationship Between Objects。), 你也可以保护一个对象的属性防止他发生改变. 这种直接创建对象的能力是 JavaScript一个杰出的特性:你可以从当前的对象(不需要类!)开始也可以慢慢的引入抽象 .例如,构造器, 对象的工场 (as discussed in Layer 3: Constructors—Factories for Instances), 相对于使用类的语言简单明了.
Dot Operator (.): 可以通过对象Keys访问属性
"."操作符提供了一种简洁的访问对象属性的的语法. 属性的 keys必须被定义 (consult Legal Identifiers). 如果你想读写对象中的任意属性值,你只需要在方括号中加入你要的属性值的名字 (see Bracket Operator ([]): Accessing Properties via Computed Keys).
The examples in this section work with the following object:
var
jane
=
{
name
:
'Jane'
,
describe
:
function
()
{
return
'Person named '
+
this
.
name
;
}
};
Getting properties
'.'操作符通过 “get” 方法读取他的值. 例子如下:
> jane.name // get property `name`
'Jane'
> jane.describe // get property `describe`
[Function]
获取对象不存在的属性值时返回 undefined
:
> jane.unknownProperty
undefined
回调函数
"."操作符也可以使用回调函数,代码如下:
> jane.describe() // call method `describe`
'Person named Jane'
Setting properties
你也可以使用等号 (=
) 对属性从新赋值. 代码如下:
> jane.name = 'John'; // set property `name`
> jane.describe()
'Person named John'
如果一个属性不存在, 往里面赋值的时候会自动创建这个对象的属性. 如果他的属性存在那么改变他原有的属性.
Deleting properties
delete
操作符可以删除对象的全部属性(the whole key-value pair). 代码如下:
> var obj = { hello: 'world' };
> delete obj.hello
true
> obj.hello
undefined
如果你仅仅是将对象的属性值定义为 undefined
, 对象的属性依旧存在且包含他的 key:
> var obj = { foo: 'a', bar: 'b' }; > obj.foo = undefined;
> Object.keys(obj)
[ 'foo', 'bar' ]
如果删除他的属性则他的 key 也被删除:
> delete obj.foo
true
> Object.keys(obj)
[ 'bar' ]
delete
操作直接影响对象的属性. 他的原型并不受到影响 (see Deleting an inherited property).
注意:
尽量少的使用 delete
操作. 现代大多数Javascript引擎为接口构造器提供优化保持"模型"不会被改变 (简单的说: 没有属性被添加、删除).删除属性可能会因为优化而被阻止.
The return value of delete
如果属性是构造器内部的属性 delete
将返回返回false删除失败
. 代码如下.
其他不能删除的情况参见 (Getting and Defining Properties via Descriptorsexplains Object.defineProperty()
):
var
obj
=
{};
Object
.
defineProperty
(
obj
,
'canBeDeleted'
,
{
value
:
123
,
configurable
:
true
});
Object
.
defineProperty
(
obj
,
'cannotBeDeleted'
,
{
value
:
456
,
configurable
:
false
});
delete
returns false
for own properties that can’t be deleted:
> delete obj.cannotBeDeleted
false
delete
returns true
in all other cases:
> delete obj.doesNotExist
true
> delete obj.canBeDeleted
true
delete
returns true
even if it doesn’t change anything (inherited properties are never removed):
> delete obj.toString
true
> obj.toString // still there
[Function: toString]
与众不同的属性键(Unusual Property Keys)
当你不想使用保留字(例如var与function)作为变量名,你可以使用他们的属性键:
> var obj = { var: 'a', function: 'b' };
> obj.var
'a'
> obj.function
'b'
Numbers类型也可以作为对象的属性键在对象的‘字面值’中,但是他们会解析成为字符串.‘点’操作符只能在他们的属性键为标示符(identifiers)的时候来访问他们的属性值.因此,在这个时候你可以通过中括号的形式去访问(如果你想更理解标示符identifiers的含义,参见 http://en.wikipedia.org/wiki/Identifier#Identifiers_in_various_disciplines):
> var obj = { 0.7: 'abc' };
> Object.keys(obj)
[ '0.7' ]
> obj['0.7']
'abc'
你可以使用任意的字符串 (标识符和数字) 作为属性键.当你引用他们,访问他们的值的时候,你还是需要使用中括号:
> var obj = { 'not an identifier': 123 };
> Object.keys(obj)
[ 'not an identifier' ]
> obj['not an identifier']
123
中括号:通过属性键的计算访问属性的值(Bracket Operator ([]): Accessing Properties via Computed Keys)
‘点’操作符允许你访问属性值当属性键是确定的时候,而中括号则可以让你通过表达式的方式来访问属性值。
通过中括号获取属性值(Getting properties via the bracket operator)
中括号操作符让你通过表达式计算的方式获取你的属性键:
> var obj = { someProperty: 'abc' }; > obj['some' + 'Property']
'abc' > var propKey = 'someProperty';
> obj[propKey]
'abc'
你也可以访问属性值,当你的属性键不为标示符的时候:
> var obj = { 'not an identifier': 123 };
> obj['not an identifier']
123
注意:在中括号的内部,他会强制转型为string. For example:
> var obj = { '6': 'bar' };
> obj[3+3] // key: the string '6'
'bar'
利用中括号操作符进行回调(Calling methods via the bracket operator)
你可以利用中括号进行方法回调:
> var obj = { myMethod: function () { return true } };
> obj['myMethod']()
true
Setting properties via the bracket operator
类似于点操作符一样,使用中括号进行赋值:
> var obj = {};
> obj['anotherProperty'] = 'def';
> obj.anotherProperty
'def'
利用中括号删除属性(Deleting properties via the bracket operator)
类似于点操作符一样,使用中括号操作符删除属性:
> var obj = { 'not an identifier': 1, prop: 2 };
> Object.keys(obj)
[ 'not an identifier', 'prop' ]
> delete obj['not an identifier']
true
> Object.keys(obj)
[ 'prop' ]
值与对象的相互转换(Converting Any Value to an Object)
这不是一个经常发生的场景,但有的时候你需要去将任意值转化为一个对象. Object()
, 使用 function (而不是构造器),提供转型服务. 遵循以下过程:
Value | Result |
(Called with no parameters) |
|
|
|
|
|
A boolean |
|
A number |
|
A string |
|
An object |
|
Here are some examples:
> Object(null) instanceof Object
true > Object(false) instanceof Boolean
true > var obj = {};
> Object(obj) === obj
true
以下方法,判断一个值是不是对象:
function
isObject
(
value
)
{
return
value
===
Object
(
value
);
}
你也可以调用对象的构造器,作为函数去回调会产生一样的结果:
> var obj = {};
> new Object(obj) === obj
true > new Object(123) instanceof Number
true
this作为函数与方法的隐式参数(this as an Implicit Parameter of Functions and Methods)
当你回调函数的时候,"this"经常作为隐式的参数:
- 一般函数'sloppy模式"下
-
虽然在一般的函数中没有使用
this
,但是 it依然作为特殊的全局对象 存在 (window
in browsers; see The Global Object):> function returnThisSloppy() { return this }
> returnThisSloppy() === window
true - 一般函数‘strict 模式’下
-
this
被定义为undefined
:> function returnThisStrict() { 'use strict'; return this }
> returnThisStrict() === undefined
true - Methods
-
this 被object方法引用时,方法得到调用
:> var obj = { method: returnThisStrict };
> obj.method() === obj
true
在一些方法中, this的 值作为方法回调的接收器.
使用回调函数(call(), apply(), and bind())给 this赋值
记住functions也是对象。因此,每个 function 都有属于他自己的方法。这些 function 再使用回调时分为3个部分。在使用这些回调函数的时候有一些陷阱 .再引用上面jane对象, jane
:
var
jane
=
{
name
:
'Jane'
,
sayHelloTo
:
function
(
otherName
)
{
'use strict'
;
console
.
log
(
this
.
name
+
' says hello to '
+
otherName
);
}
};
Function.prototype.call(thisValue, arg1?, arg2?, ...)
第一个参数是 function内部调用的值,剩下的作为函数的参数被函数自身调用。以下3种调用方式是等价的:
jane
.
sayHelloTo
(
'Tarzan'
);
jane
.
sayHelloTo
.
call
(
jane
,
'Tarzan'
);
var
func
=
jane
.
sayHelloTo
;
func
.
call
(
jane
,
'Tarzan'
);
在第二个回调步骤中,你需要重复的传入 jane 对象 ,因为 call()方法在被调用的时候不知道你是如何获取 function 的.
Function.prototype.apply(thisValue, argArray)
第一个参数是 function内部调用的值,而第二个数组作为函数被调用的参数. 以下3种调用方式是等价的:
jane
.
sayHelloTo
(
'Tarzan'
);
jane
.
sayHelloTo
.
apply
(
jane
,
[
'Tarzan'
]);
var
func
=
jane
.
sayHelloTo
;
func
.
apply
(
jane
,
[
'Tarzan'
]);
在第二个回调步骤中,你需要重复的传入 jane 对象 ,因为apply()方法在被调用的时候不知道你是如何获取 function 的 .
Function.prototype.bind(thisValue, arg1?, ..., argN?)
这个方法执行局部的函数应用-意味着它将创建一个bind()回调函数的接收器: thisValue
和 arg1
.. argN作为新函数的参数
.见一下例子:
function
func
()
{
console
.
log
(
'this: '
+
this
);
console
.
log
(
'arguments: '
+
Array
.
prototype
.
slice
.
call
(
arguments
));
}
var
bound
=
func
.
bind
(
'abc'
,
1
,
2
);
数组的 slice
将 arguments转型为
数组, 记录他们是必要的 (this operation is explained in Array-Like Objects and Generic Methods). bound
是一个新的函数. 见以下代码:
> bound(3)
this: abc
arguments: 1,2,3
The following three invocations of sayHelloTo
are all equivalent:
jane
.
sayHelloTo
(
'Tarzan'
);
var
func1
=
jane
.
sayHelloTo
.
bind
(
jane
);
func1
(
'Tarzan'
);
var
func2
=
jane
.
sayHelloTo
.
bind
(
jane
,
'Tarzan'
);
func2
();
构造器手动模拟apply()(Manually simulating an apply() for constructors)
我们分两个阶段手动模拟 apply()
.
- Step 1
-
给Date对象传递参数并回调 (参数暂时不为数组):
new
(
Date
.
bind
(
null
,
2011
,
11
,
24
))
代码被
bind()使用之前,会创建一个无参的构造器并且为之调用
. - Step 2
-
用
apply()为
bind()传递数组
.因为bind()是回调方法
,我们可以使用apply()
:new
(
Function
.
prototype
.
bind
.
apply
(
Date
,
[
null
,
2011
,
11
,
24
]))
数组在使用之前有很多的元素,与
null
. 我们在此之前可以使用concat()
:var
arr
=
[
2011
,
11
,
24
];
new
(
Function
.
prototype
.
bind
.
apply
(
Date
,
[
null
].
concat
(
arr
)))
陷阱:方法中Functions的 this 阴影(Pitfall: Functions Inside Methods Shadow this)
如下: function 在 (1)尝试访问方法 (2)处的 this
:
var
obj
=
{
name
:
'Jane'
,
friends
:
[
'Tarzan'
,
'Cheeta'
],
loop
:
function
()
{
'use strict'
;
this
.
friends
.
forEach
(
function
(
friend
)
{
// (1)
console
.
log
(
this
.
name
+
' knows '
+
friend
);
// (2)
}
);
}
};
很明显, 失败, 因为 function 在 (1) 处 有他自身的 this
,在这里是 undefined
:
> obj.loop();
TypeError: Cannot read property 'name' of undefined
有3种解决此问题的方式.
Workaround 1: that = this
我们将this定义成为一个变量:
loop
:
function
()
{
'use strict'
;
var
that
=
this
;
this
.
friends
.
forEach
(
function
(
friend
)
{
console
.
log
(
that
.
name
+
' knows '
+
friend
);
});
}
结果为:
> obj.loop();
Jane knows Tarzan
Jane knows Cheeta
Workaround 2: bind()
使用 bind()
对 this进行回调
—换句话说, 也就是方法(1)中的 this
(line (1)):
loop
:
function
()
{
'use strict'
;
this
.
friends
.
forEach
(
function
(
friend
)
{
console
.
log
(
this
.
name
+
' knows '
+
friend
);
}.
bind
(
this
));
// (1)
}
Workaround 3: a thisValue for forEach()
forEach()方法提供了第二个参数
(see Examination Methods) 进行回调 this
:
loop
:
function
()
{
'use strict'
;
this
.
friends
.
forEach
(
function
(
friend
)
{
console
.
log
(
this
.
name
+
' knows '
+
friend
);
},
this
);
}
Layer 1: Single Objects的更多相关文章
- Chapter 17. Objects and Inheritance(对象与继承)
javascript面向对象编程有几个层面: 1: 单一对象 (covered in Layer 1: Single Objects) 2: 对象之间的 prototype (described i ...
- Performance Optimization (2)
DesktopGood performance is critical to the success of many games. Below are some simple guidelines f ...
- [非官方]ArcGIS10.2 for Desktop扩展工具包——XTools Pro
XTools Pro 是一套为ArcGIS平台设计的矢量空间分析. 形状转换和表管理扩展工具,大大增强了 ArcGIS 的功能,使用该工具能够提高 ArcGIS 用户的效率和性能. XTools Pr ...
- 说说 DWRUtil
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp27 说说 DWRUtil 比如我们从服务器端获得了一个citylist的数 ...
- 3DSMAX中英文对比大全(从A-Z分类)
A Absolute Mode Transform Type-in绝对坐标方式变换输入 Absolute/Relative Snap Toggle Mode绝对/相对捕捉开关模式 ACIS Optio ...
- (转载)23种设计模式的uml图表示及通俗介绍
转载自: https://www.cnblogs.com/ningskyer/articles/3615312.html 0.分类 创建型模式 1.FACTORY2.BUILDER3.FACTORY ...
- Streamline Your App with Design Patterns 用设计模式精简你的应用程序
Back to Design Patterns Streamline Your App with Design Patterns 用设计模式精简你的应用程序 In Objective-C progra ...
- Framework for Graphics Animation and Compositing Operations
FIELD OF THE DISCLOSURE The subject matter of the present disclosure relates to a framework for hand ...
- Advanced Architecture for ASP.NET Core Web API
转自: https://www.infoq.com/articles/advanced-architecture-aspnet-core ASP.NET Core's new architecture ...
随机推荐
- nodejs中npm工具自身升级
npm官方地址:https://www.npmjs.com/ npm在github上的地址:https://github.com/npm/npm 目前(截止2016-03-15)npm最新版本为3.8 ...
- JavaScript入门(8)
一.什么是对象 JavaScript中的所有事物都是对象.如:字符串.数值.数组.函数等.每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的.如:字符串的长度.图像的长宽 对象的方法:能 ...
- 你hack那么多啊,该怎么办
当我们通过javascript来操作css样式的时候,假如我们停留在css2的阶段,会发现操作起来并不是很困难.虽然存在一些浏览器兼容的问题,但我们通过封装自己的函数,不仅可以设置样式还能够获取样式. ...
- 实现html伪静态竟然那么简单
1.单参数 功能: 把:www.44721.cn/movie.asp?id=123 伪静态为:www.44721.cn/movie.asp?123.html 代码如下: ASP/Visual Basi ...
- 常用经典SQL语句大全(基础)
一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sqlserver --- 创 ...
- SQL SERVER删除列,报错."由于一个或多个对象访问此列,ALTER TABLE DROP COLUMN ... 失败"
队友给我修改数据的语句.总是执行失败.很纳闷. 如下图: 仔细看了下这个列,并没有什么特殊.如下图: 但其确实有个约束: 'DF__HIS_DRUG___ALL_I__04E4BC85' . 为什么有 ...
- 11_Servlet生命周期
[生命周期] 以前:之前的java程序,我们的Java类自己去new对象,自已实例化对象去调用. 现在:Servlet程序,Servlet的生命周期由TomCat服务器控制的. 我们要研究Servle ...
- js中的in-for循环
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...
- csdn博客刷粉代码
原理是当有访客访问博客时,执行js实现自动加粉丝,达到刷粉的目的. <script src="http://code.jquery.com/jquery-1.4.1.min.js&qu ...
- Jquery ajax使用json形式通信
前台JS $.ajax({ type: 'post', url: 'HandlerL ...