首頁 web前端 js教程 JavaScript極簡入門教學(二):物件與函數_javascript技巧

JavaScript極簡入門教學(二):物件與函數_javascript技巧

May 16, 2016 pm 04:32 PM
javascript 入門教學 函數 物件

閱讀本文需有其他語言的程式設計經驗。

JavaScript 中的簡單型別包括:

1.數字
2.字串
3.布爾(true 和 false)
4.null
5.undefined

此外的其他類型皆是物件(我們不要被 typeof 運算子的回傳值所迷惑),例如:

1.函數
2.數組
3.正規表示式
4.對象(對象自然也是對象)

物件基礎

在 JavaScript 中,物件是屬性的集合(物件為關聯陣列),每個屬性都包括:

1.屬性名,必須為字串
2.屬性值,可以為除了 undefined 之外的任何值

透過物件 literal 建立物件:

複製程式碼 程式碼如下:

// 透過物件 literal {} 建立空物件
var empty_object = {};

物件的屬性名稱和屬性值:

複製程式碼 程式碼如下:

var stooge = {
    // "first-name" 為屬性名,"Jerome" 為屬性值
    "first-name": "Jerome",
    // "last-name" 為屬性名,"Howard" 為屬性值
    "last-name": "Howard"
};

如果屬性名稱是合法的標識符,那麼可以省略引號:

複製程式碼 程式碼如下:

var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};

我們來看屬性存取的範例:

複製程式碼 程式碼如下:

var owner = { name: "Name5566" };
 
owner.name; // "Name5566"
owner["name"]; // "Name5566"
 
owner.job; // undefined
owner.job = "coder"; // 或 owner["job"] = "coder";

如果屬性名不是合法標識符,那麼就需要用引號包裹。不存在的屬性值為 undefined。物件是透過引用而非按值傳遞:

複製程式碼 程式碼如下:

var x = {};
var owner = x;
owner.name = "Name5566";
x.name; // x.name === "Name5566"

這裡 x 和 owner 引用同一個物件。

物件的屬性可以使用 delete 運算子刪除:

複製程式碼 程式碼如下:

delete obj.x; // 刪除物件 obj 的 x 屬性

物件的原型(prototype)

每一個物件都被連結了一個原型物件(prototype object),物件能夠從原型物件繼承屬性。我們透過物件 literal 建立一個對象,它的原型物件為 Object.prototype 物件(Object.prototype 物件本身沒有原型物件)。我們在創建物件的時候,可以設定物件的原型物件(之後再討論具體的設定方法)。在嘗試取得(而非修改)物件的某個屬性時,如果該物件不存在此屬性,那麼JavaScript 會嘗試從此物件的原型物件中取得此屬性,如果原型物件中沒有該屬性,那麼再從此原型對象的原型物件中查找,以此類推,直到Object.prototype 原型物件。相較於獲取屬性而言,我們修改物件的某個屬性時,不會影響原型物件。

函數基礎

在 JavaScript 中函數也是對象,其連結到 Function.prototype 原型對象(Function.prototype 連結到 Object.prototype)。函數存在一個名為 prototype 的屬性,其值的類型為對象,此物件存在一個屬性 constructor,constructor 的值為此函數:

複製程式碼 程式碼如下:

var f = function() {}
 
typeof f.prototype; // 'object'
typeof f.prototype.constructor; // 'function'
 
f === f.prototype.constructor; // true

函數是對象,你可以像使用對像一樣使用函數,也就是說,函數可以保存在變數、陣列中,可以作為參數傳遞給函數,函數內部可以定義函數。附帶提及一下,函數有兩個被隱藏的屬性:

1.函數的上下文
2.函數的程式碼

函數的建立如下:

複製程式碼 程式碼如下:

var f = function add(a, b) {
    return a b;
}
 
console.log(f); // 輸出 [Function: 加]

關鍵字 function 後的函數名稱是可選的,我們制定函數名稱主要出於幾個目的:

1.為了遞歸呼叫
2.被調試器、開發工具等用來識別函數

很多時候我們並不需要函數名,沒有函數名的函數被叫做匿名函數。有括號包裹的為參數清單。 JavaScript 不要求實參和形參匹配,例如:

複製程式碼 程式碼如下:

var add = function(a, b) {
    return a b;
}
 
add(1, 2, 3); // 實參和形參不符

如果實參過多,那麼多餘的實參會被忽略,如果實參過少,那麼未被賦值的形參的值為 undefined。函數一定有一個回傳值,如果沒有透過 return 語句指定回傳值,那麼函數傳回值為 undefined。

一個函數和其存取的外部變數組成一個閉包。這就是 JavaScript 的關鍵魅力。

函數呼叫

每個函數被呼叫時,會接收到兩個額外的參數:

1.this
2.arguments

this 的值和具體呼叫的模式有關,在 JavaScript 中有四種呼叫模式:

1.方法呼叫模式。物件的屬性如果是函數,則稱為方法。如果一個方法透過 o.m(args) 被調用,this 為物件 o(由此可見,在調用時,this 和 o 才進行綁定),例如:

複製程式碼 程式碼如下:

var obj = {
    value: 0,
    increment: function(v) {
        this.value = (typeof v === 'number' ? v : 1);
    }
};
obj.increment(); // this === obj

2.函數呼叫模式。如果一個函數不是一個物件的屬性,那麼它將作為一個函數被調用,這時候 this 被綁定到全域物件上,例如:

複製程式碼 程式碼如下:

message = 'Hello World';
var p = function() {
 console.log(this.message);
}
 
p(); // 輸出 'Hello World'

這種行為有時候讓人疑惑,看一個例子:

複製程式碼 程式碼如下:

obj = {
    value: 0,
    increment: function() {
        var helper = function() {
            // 對全域物件中的 value 加上 1
            this.value = 1;
        }
 
        // helper 被當作一個函數來呼叫
        // 因此 this 為全域物件
        helper();
    }
};
 
obj.increment(); // obj.value === 0

我們預期的結果應該是:

複製程式碼 程式碼如下:

obj = {
    value: 0,
    increment: function() {
        var that = this;
        var helper = function() {
            that.value = 1;
        }
 
        helper();
    }
};
 
obj.increment(); // obj.value === 1

3.建構函式呼叫模式。意圖使用 new 前綴的函數稱為建構函數,例如:

複製程式碼 程式碼如下:

// Test 被叫做建構子
var Test = function(string) {
    this.message = string;
}
 
var myTest = new Test("Hello World");

一個函數前面可以加上 new 來呼叫(這樣的函數通常大寫開頭),加上 new 之後將建立一個連結到此函數的 prototype 屬性的對象,且建構函式中 this 為此對象。

4.apply 呼叫模式。函數的 apply 方法被用來呼叫函數,其有兩個參數,第一個為 this,第二個為參數數組,例如:

複製程式碼 程式碼如下:

var add = function(a, b) {
    return a b;
}
 
var ret = add.apply(null, [3, 4]); // ret === 7

函數呼叫時,我們能夠存取一個名為 arguments 的類別數組(非真正的 JavaScript 數組),其包含了所有的實參,這樣我們就能實現變長參數:

複製程式碼 程式碼如下:

var add = function() {
    var sum = 0;
    for (var i=0; i         sum = arguments[i];
    }
    return sum;
}
 
add(1, 2, 3, 4);

異常

現在來說說 JavaScript 的異常處理機制。我們使用 throw 語句來拋出異常,try-cache 語句來捕捉並處理異常:

複製程式碼 程式碼如下:

var add = function (a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        // 拋出異常
        throw {
            name: '類型Error',
            message: 'add needs numbers'
        };
    }
    return a b;
}
 
// 捕捉並處理異常
try {
    add("seven");
// e 為拋出的異常物件
} catch (e) {
    console.log(e.name ': ' e.message);
}

為JavaScript 類型新增屬性

JavaScript 中大多數型別存在建構子:

1.物件的建構子為 Object
2.數組的建構子為 Array
3.函數的建構子為 Function
4.字串的建構子為 String
5.數字的建構子為 Number
6.布林的建構子為 Boolean
7.正規表示式的建構子為 RegExp

我們可以為建構函式的 prototype 新增屬性(常加法),使得此屬性對相關變數可用:

複製程式碼 程式碼如下:

Number.prototype.integer = function() {
    return Math[this }
 
(1.1).integer(); // 1

作用域

JavaScript 需要透過函數來建構作用域:

複製程式碼 程式碼如下:

function() {
    // ...
}();

這裡建立並執行了一個匿名函數。透過作用域能夠隱藏不希望暴露的變數:

複製程式碼 程式碼如下:

var obj = function() {
    // 隱藏 value,外部無法存取
    var value = 0;
 
    return {
        // 僅此方法可以修改 value
        increment: function() {
            value = 1;
        },
        // 僅此方法可讀取 value
        getValue: function() {
            return value;
        }
    };
}();
 
obj.increment();
obj.getValue() === 1;

繼承

JavaScript 實作繼承的方式很多。
在創建對象時,我們可以設定對象關聯的原型對象,我們這樣做:

複製程式碼 程式碼如下:

// 建立一個物件 o,其原型物件為 {x:1, y:2}
var o = Object.create({x:1, y:2});

Object.create 方法被定義在 ECMAScript 5 中,如果你使用 ECMAScript 3 時可以自己實作一個 create 方法:

複製程式碼 程式碼如下:

// 如果未定義 Object.create 方法
if (typeof Object.create !== 'function') {
    // 建立 Object.create 方法
    Object.create = function (o) {
        var F = function () {};
        F.prototype = o;
        // 建立一個新對象,此對象的原型對象為 o
        return new F();
    };
}

透過 Object.create 方法我們進行基於原型繼承:一個新物件直接繼承一個舊物件的屬性(相對於基於類別的繼承,這裡無需類別的存在,物件直接繼承物件)。範例:

複製程式碼 程式碼如下:

var myMammal = {
    name: 'Herb the Mammal',
    get_name: function() {
        return this.name;
    },
    says: function() {
        return this.saying || '';
    }
};
 
// 繼承 myMammal
var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.purr = function(n) {
    var i, s = '';
    for (i = 0; i         if (s) {
            s = '-';
        }
        s = 'r';
    }
    return s;
};
myCat.get_name = function() {
    return this.says() ' ' this.name ' ' this.says();
};

上面的程式碼很簡單,但沒辦法保護私有成員。我們可以使用模組模式。在模組模式中,某一類物件由一個函數產生,並利用函數作用域保護私有成員不被外部存取:

複製程式碼 程式碼如下:

// mammal 函數,用於建構 mammal 物件
var mammal = function(spec) {
    // that 為構造的物件
    var that = {};
 
    // 公有方法 get_name 可外部存取
    that.get_name = function() {
        // spec.name 外在無法直接存取
        return spec.name;
    };
 
    // 公有方法 says 外部存取
    that.says = function() {
        // spec.saying 外在無法直接存取
        return spec.saying || '';
    };
 
    return that;
};
 
// 建立 mammal 物件
var myMammal = mammal({name: 'Herb'});
 
// cat 函數,用於建構 cat 物件
var cat = function(spec) {
    spec.saying = spec.saying || 'meow';
 
    // cat 繼承自 mammal,因此先建構出 mammal 物件
    var that = mammal(spec);
 
    // 加入公有方法 purr
    that.purr = function(n) {
        var i, s = '';
        for (i = 0; i             if (s) {
                s = '-';
            }
            s = 'r';
        }
        return s;
    };
 
    // 修改公有方法 get_name
    that.get_name = function() {
        return that.says() ' ' spec.name
            ' ' that.says();
        return that;
    };
};
 
// 建立 cat 物件
var myCat = cat({name: 'Henrietta'});

在模組模式中,繼承是透過呼叫建構子來實現的。另外,我們也可以在子類別中存取父類別的方法:

複製程式碼 程式碼如下:

Object.prototype.superior = 函數(名稱) {
    var that = this, method = that[名稱];
    回傳函數() {
        return method.apply(that,arguments);
    };
};
 
var Coolcat = 函數(規格){
    // 取得子類別的 get_name 方法
    var that = cat(spec), super_get_name = that.superior('get_name');
    that.get_name = function(n) {
        return 'like ' super_get_name() 'baby';
    };
    返回;
};

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

golang函數動態建立新函數的技巧 golang函數動態建立新函數的技巧 Apr 25, 2024 pm 02:39 PM

Go語言提供了兩種動態函數創建技術:closures和反射。 closures允許存取閉包作用域內的變量,而反射可使用FuncOf函數建立新函數。這些技術在自訂HTTP路由器、實現高度可自訂的系統和建置可插拔的元件方面非常有用。

C++ 函數命名中參數順序的考慮 C++ 函數命名中參數順序的考慮 Apr 24, 2024 pm 04:21 PM

在C++函數命名中,考慮參數順序至關重要,可提高可讀性、減少錯誤並促進重構。常見的參數順序約定包括:動作-物件、物件-動作、語意意義和遵循標準函式庫。最佳順序取決於函數目的、參數類型、潛在混淆和語言慣例。

如何在Java中寫出高效和可維護的函數? 如何在Java中寫出高效和可維護的函數? Apr 24, 2024 am 11:33 AM

編寫高效且可維護的Java函數的關鍵在於:保持簡潔。使用有意義的命名。處理特殊情況。使用適當的可見性。

如何將 MySQL 查詢結果陣列轉換為物件? 如何將 MySQL 查詢結果陣列轉換為物件? Apr 29, 2024 pm 01:09 PM

將MySQL查詢結果陣列轉換為物件的方法如下:建立一個空物件陣列。循環結果數組並為每一行建立一個新的物件。使用foreach迴圈將每一行的鍵值對賦給新物件的對應屬性。將新物件加入到物件數組中。關閉資料庫連線。

excel函數公式大全 excel函數公式大全 May 07, 2024 pm 12:04 PM

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

C++ 函式預設參數與可變參數的優缺點比較 C++ 函式預設參數與可變參數的優缺點比較 Apr 21, 2024 am 10:21 AM

C++函數中預設參數的優點包括簡化呼叫、增強可讀性、避免錯誤。缺點是限制靈活性、命名限制。可變參數的優點包括無限彈性、動態綁定。缺點包括複雜性更高、隱式型別轉換、除錯困難。

數組和物件在 PHP 中的差異是什麼? 數組和物件在 PHP 中的差異是什麼? Apr 29, 2024 pm 02:39 PM

PHP中,數組是有序序列,以索引存取元素;物件是具有屬性和方法的實體,透過new關鍵字建立。數組存取透過索引,物件存取通過屬性/方法。數組值傳遞,物件參考傳遞。

自訂 PHP 函數和預定義函數之間有什麼區別? 自訂 PHP 函數和預定義函數之間有什麼區別? Apr 22, 2024 pm 02:21 PM

自訂PHP函數與預定義函數的差異在於:作用域:自訂函數僅限於其定義範圍,而預定義函數可在整個腳本中存取。定義方式:自訂函數使用function關鍵字定義,而預先定義函數則由PHP核心定義。參數傳遞:自訂函數接收參數,而預先定義函數可能不需要參數。擴充性:自訂函數可以根據需要創建,而預定義函數是內建的且無法修改。

See all articles