本文共 4921 字,大约阅读时间需要 16 分钟。
================================================================================
Qomolangma OpenProject v0.9 类别 :Rich Web Client关键词 :JS OOP,JS Framwork, Rich Web Client,RIA,Web Component, DOM,DTHML,CSS,JavaScript,JScript项目发起:aimingoo ()
项目团队:aimingoo, leon()有贡献者:JingYu()================================================================================ 八、JavaScript面向对象的支持~~~~~~~~~~~~~~~~~~(续)7. JavaScript面向对象的支持的补充内容
-------- 1). 类型系统========================我们前面已经完整地描述过JavaScript的两种类型系统。包括: - 基础类型系统:由typeof()返回值的六种基础类型 - 对象类型系统:由new()返回值的、构造器和原型继承组织起来的类型系统JavaScript是弱类型语言,因此类型自动转换是它语言特性的一个重要组成部分。但
对于一个指定的变量而言,(在某一时刻,)它总是有确定的数据类型的。“运算”是导致类型转换的方法(但不是根源),因此“运算结果的类型”的确定就非常重要。关于这一部分的内容,推荐大家阅读一份资料:类型系统中还有一个特殊的组成部分,就是“直接量”声明。下面的代码简述各种直
接量声明的方法,但不再详述具体细节://---------------------------------------------------------// 各种直接量声明(一些错误格式或特例请查看JScript手册)//---------------------------------------------------------// 1. Numbervar n1 = 11; // 普通十进制数var n2 = 013; // 八进制数var n3 = 0xB; // 十六进制数var n4 = 1.2; // 浮点值var n5 = .2; // 浮点值var n6 = 1.0e-4; // (或1e-4)浮点值// 2. Stringvar s1 = 'test'; // (或"test")字符串var s2 = "test/n";// 带转义符的字符串(转义符规则参见手册)var s3 = "'test'";// 用""、''以在字符串中使用引号var s4 = "/xD"; // 用转义符来声明不可键入的字符
// 3. Booleanvar b1 = true;var b2 = false;
// 4. Functionfunction foo1() {}; // 利用编译器特性直接声明var foo2 = function() {}; // 声明匿名函数
// 5. Object// * 请留意声明中对分隔符“,”的使用var obj1 = null; // 空对象是可以被直接声明的var obj2 = { value1 : 'value', // 对象属性 foo1 : function() {}, // 利用匿名函数来直接声明对象方法 foo2 : foo2 // 使方法指向已声明过的函数}
// 6. RegExpvar r1 = /^[O|o]n/; // 使用一对"/../"表达的即是正则表达式var r2 = /^./gim; // (注意,) gim为正则表达式的三个参数
// 7. Arrayvar arr1 = [1,,,1]; // 直接声明, 包括一些"未定义(undefined)"值var arr2 = [1,[1,'a']]; // 异质(非单一类型)的数组声明var arr3 = [[1],[2]]; // 多维数组(其实是从上一个概念衍生下来的
// 8. undefinedvar u1 = undefined; // 可以直接声明, 这里的undefined是Global的属性
有些时候,我们可以“即声明即使用”一个直接量,下面的代码演示这一特性://---------------------------------------------------------// 直接量的“即声明即使用”//---------------------------------------------------------var obj = function () { // 1. 声明了一个匿名函数 return { // 2. 函数执行的结果是返回一个直接声明的"对象" value: 'test', method: function(){} }}(); // 3. 使匿名函数执行并返回结果,以完成obj变量的声明
在这个例子中,很多处用到了直接量的声明。这其中函数直接声明(并可以立即执行)的特
性很有价值,例如在一个.js文件中试图执行一些代码,但不希望这些代码中的变量声明对全局代码导致影响,因此可以在外层包装一个匿名函数并使之执行,例如://---------------------------------------------------------// 匿名函数的执行// (注:void用于使后面的函数会被执行, 否则解释器会认为仅是声明函数)//---------------------------------------------------------void function() { if (isIE()) { // do something... }}(); 2). 对象系统========================对象系统中一个未被提及的重要内容是delete运算。它用于删除数组元素、对象属性和已声明的变量。由于delete运算不能删除用var来声明的变量,也就意味着它只能删除在函数内/外声明
的全局变量。——这个说法有点别扭,但事实上的确如此。那么我们可以更深层地透视一个真想:delete运算删除变量的实质,是删除用户在window对象的上下文环境中声明的属性。回到前面有关“上下文环境”的讨论,我们注意到(在函数外)声明全局变量的三种形式:
----------var global_1 = '全局变量1';global_2 = '全局变量2';function foo() { global_3 = '全局变量3';}----------
全局变量2和3都是“不用var声明的变量”,这其实是在window对象的上下文环境中的
属性声明。也就是说可以用window.global_2和window.global_3来存取它们。这三种声明window对象的属性的方法,与直接指定“window.global_value = <值>”这种方法的唯一区别,是在“for .. in”运算时,这三种方法声明的属性/方法都会被隐藏。如下例所示://---------------------------------------------------------// 全局变量上下文环境的一些特点:属性名隐藏//---------------------------------------------------------var global_1 = '全局变量1';global_2 = '全局变量2';void function foo() { global_3 = '全局变量3';}();
window.global_4 = '全局变量4';
for (var i in window) { document.writeln(i, '<br>');}document.writeln('<HR>');document.writeln(window.global_1, '<BR>');document.writeln(window.global_2, '<BR>');document.writeln(window.global_3, '<BR>');
我们注意到在返回的结果中不会出现全局变量1/2/3的属性名。但使用window.xxxx这种方
式仍可以存取到它们。在window上下文环境中,global_1实质是该上下文中的私有变量,我们在其它代码中能存
取到它,只是因为其它(所有的)代码都在该上下文之内。global_2/3则被(隐含地)声明成window的属性,而global_4则显式地声明为window的属性。因此我们回到前面的结论:
- 删除(不用var声明的)变量的实质,是删除window对象的属性。此外,我们也得到另外三条推论(最重要的是第一条):
- delete能删除数组元素,实质上是因为数组下标也是数组对象的隐含属性。 - 在复杂的系统中,为减少变量名冲突,应尽量避免全局变量(和声明)的使用,或采用 delete运算来清理window对象的属性。 - window对象是唯一可以让用户声明“隐含的属性”的对象。——注意这只是表面的现 象,因为事实上这只是JavaScript规范带来的一个“附加效果”。:)delete清除window对象、系统对象、用户对象等的“用户声明属性”,但不能清除如prototype、
constructor这样的系统属性。此外,delete也可以清除数组中的元素(但不会因为清除元素而使数组长度发生变化)。例如://---------------------------------------------------------// delete运算的一些示例//---------------------------------------------------------var arr = [1, 2, 3];var obj = {v1:1, v2:2};global_variant = 3;delete arr[2];document.writeln('1' in arr, '<BR>'); // 数组下标事实上也是数组对象的隐含属性document.writeln(arr.length, '<BR>'); // 数组长度不会因delete而改变
delete obj.v2;document.writeln('v2' in obj, '<BR>');
document.writeln('global_variant' in window, '<BR>');delete global_variant;
// 以下的代码不能正常执行,这是IE的一个bugif ('global_variant' in window) { document.writeln('bug test:', global_variant, '<BR>');}
最后这行代码错误的根源,在于IE错误地检测了'global_variant'在window的对象属性
中是否仍然存在。因为在同样的位置,“('global_variant' in window)”表达式的返回结果居然为true!——firefox中没有这个bug。delete清除掉属性或数组元素,并不表明脚本引擎会对于该属性/元素执行析构。对象
的析构操作是不确定的,关于这一点请查看更前面的内容。转载地址:http://aehbb.baihongyu.com/