JavaScript物件導向的支援(7)

來源:互聯網
上載者:User

================================================================================
Qomolangma OpenProject v0.9

類別    :Rich Web Client
關鍵詞  :JS OOP,JS Framwork, Rich Web Client,RIA,Web Component,
          DOM,DTHML,CSS,JavaScript,JScript

項目發起:aimingoo (aim@263.net)
項目團隊:aimingoo, leon(pfzhou@gmail.com)
有貢獻者:JingYu(zjy@cnpack.org)
================================================================================

八、JavaScript物件導向的支援
~~~~~~~~~~~~~~~~~~
(續)

7. JavaScript物件導向的支援的補充內容
--------
 1). 類型系統
========================
我們前面已經完整地描述過JavaScript的兩種類型系統。包括:
  - 基礎類型系統:由typeof()傳回值的六種基礎類型
  - 物件類型系統:由new()傳回值的、構造器和原型繼承組織起來的類型系統

JavaScript是弱類型語言,因此類型自動轉換是它語言特性的一個重要組成部分。但
對於一個指定的變數而言,(在某一時刻,)它總是有確定的資料類型的。“運算”是
導致類型轉換的方法(但不是根源),因此“運算結果的類型”的確定就非常重要。關
於這一部分的內容,推薦大家閱讀一份資料:
  http://jibbering.com/faq/faq_notes/type_convert.html

類型系統中還有一個特殊的組成部分,就是“直接量”聲明。下面的代碼簡述各種直
接量聲明的方法,但不再詳述具體細節:
//---------------------------------------------------------
// 各種直接量聲明(一些錯誤格式或特例請查看JScript手冊)
//---------------------------------------------------------
// 1. Number
var n1 = 11;      // 普通十進位數
var n2 = 013;     // 八位元
var n3 = 0xB;     // 十六進位數
var n4 = 1.2;     // 浮點值
var n5 =  .2;     // 浮點值
var n6 = 1.0e-4;  // (或1e-4)浮點值

// 2. String
var s1 = 'test';  // (或"test")字串
var s2 = "test/n";// 帶轉義符的字串(轉義符規則參見手冊)
var s3 = "'test'";// 用""、''以在字串中使用引號
var s4 = "/xD";   // 用轉義符來聲明不可鍵入的字元

// 3. Boolean
var b1 = true;
var b2 = false;

// 4. Function
function foo1() {};       // 利用編譯器特性直接聲明
var foo2 = function() {}; // 聲明匿名函數

// 5. Object
// * 請留意聲明中對分隔字元“,”的使用
var obj1 = null;          // Null 物件是可以被直接聲明的
var obj2 = {
  value1 : 'value',       // 對象屬性
  foo1   : function() {}, // 利用匿名函數來直接聲明對象方法
  foo2   : foo2           // 使方法指向已聲明過的函數
}

// 6. RegExp
var r1 = /^[O|o]n/;     // 使用一對"/../"表達的即是Regex
var r2 = /^./gim;       // (注意,) gim為Regex的三個參數

// 7. Array
var arr1 = [1,,,1];     // 直接聲明, 包括一些"未定義(undefined)"值
var arr2 = [1,[1,'a']]; // 異質(非單一類型)的數組聲明
var arr3 = [[1],[2]];   // 多維陣列(其實是從上一個概念衍生下來的

// 8. undefined
var 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的一個bug
if ('global_variant' in window) {
 document.writeln('bug test:', global_variant, '<BR>');
}

最後這行代碼錯誤的根源,在於IE錯誤地檢測了'global_variant'在window的對象屬性
中是否仍然存在。因為在同樣的位置,“('global_variant' in window)”運算式的返
回結果居然為true!——firefox中沒有這個bug。

delete清除掉屬性或數組元素,並不表明指令碼引擎會對於該屬性/元素執行析構。對象
的析構操作是不確定的,關於這一點請查看更前面的內容。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.