JavaScript物件導向精要(一)

來源:互聯網
上載者:User

JavaScript物件導向精要(一)
資料類型

在JavaScript中,資料類型分為兩類:

原始類型:儲存一些簡單資料,如true,5等。JavaScript共有5中原始類型:
boolean:布爾,值為true或false number:數字,值為任何整型會浮點數值 string:字串,值為由單引號或雙引號括出的單個字元或連續字元(JavaScript不區分字元類型) null:空類型,其僅有一個值:nulll undefined:未定義,其僅有一個值:undefined
var name = "Pomy";var blog = "http://www.ido321.com";var age = 22;alert(typeof blog); //"string"alert(typeof age); //"number"

原始類型的值是直接儲存在變數中,並可以用typeof進行檢測。但是typeof對null的檢測是返回object,而不是返回null:

//彈出Not nullif(typeof null){    alert("Not null");   }else{    alert("null");}

所以檢測null時,最好用全等於(===),其還能避免強制類型轉換:

console.log("21" === 21);  //falseconsole.log("21" == 21);  //trueconsole.log(undefined == null);  //trueconsole.log(undefined === null);  //false

對於字串、數字或者布爾值,其都有對應的方法,這些方法來自於對應的原始封裝類型:String、Number和Boolean。原始封裝類型將被自動建立。

var name = "Pomy";var char = name.charAt(0);console.log(char);  //"P"

在JavaScript引擎中發生的事情:

var name = "Pomy";var temp = new String(name);var char = temp.charAt(0);temp = null;console.log(char);  //"P"

字串對象的引用在用完之後立即被銷毀,所以不能給字串添加屬性,並且instanceof檢測對應類型時均返回false:

var name = "Pomy";name.age = 21;console.log(name.age);   //undefinedconsole.log(name instanceof String);  //false
參考型別:儲存為對象,實質是指向記憶體位置的引用,所以不在變數中儲存對象。除了自訂的對象,JavaScript提供了6中內建類型:
Array:數群組類型,以數字為索引的一組值的有序列表 Date:日期和時間類型 Error:運行期錯誤類型 Function:函數類型 Object:通用物件類型 RegExp:Regex類型
可以用new來執行個體化每一個對象,或者用字面量形式來建立對象:
var obj = new Object;var own = {            name:"Pomy",            blog:"http://www.ido321.com",            "my age":22        };console.log(own.blog);    //訪問屬性console.log(own["my age"]); obj = null;  //解除引用

obj 並不包含對象執行個體,而是一個指向記憶體中實際對象所在位置的指標(或者說引用)。因為typeof對所有非函數的參考型別均返回object,所以需要用instanceof來檢測參考型別。

函數

在JavaScript中,函數就是對象。使函數不同於其他對象的決定性特性是函數存在一個被稱為[[Call]]的內部屬性。內部屬性無法通過代碼訪問而是定義了代碼執行時的行為。

建立形式

1、函式宣告:用function關鍵字,會被提升至上下文
2、函數運算式:不能被提升
3、執行個體化Function內建類型

sayHi();    //函數提升function sayHi(){    console.log("Hello");}//其他等效等效方式/*var sayHi = function(){     console.log("Hello");}var sayHi = new Function(" console.log(\"Hello\");");*/
參數

JavaScript函數的另外一個獨特之處在於可以給函數傳遞任意數量的參數。函數參數被儲存在arguments類數組對象中,其自動存在函數中,能通過數字索引來引用參數,但它不是數組執行個體:

alert(Array.isArray(arguments));   //false

類數組對象arguments 儲存的是函數的實參,但並不會忽略形參。因而,arguments.length返回實參列表的長度,arguments.callee.length返回形參列表的長度。

function ref(value){    return value;}console.log(ref("Hi"));console.log(ref("Hi",22));console.log(ref.length);  //1
函數中的this

關於this的問題,可參考此文:JavaScript中的this。
JavaScript提供了三個方法用於改變this的指向:call、apply和bind。三個函數的第一個參數都是指定this的值,其他參數均作為參數傳遞給函數。

對象

對象是一種參考型別,建立對象常見的兩種方式:Object建構函式和對象字面量形式:

var per1 = {    name:"Pomy",    blog:"http://www.ido321.com"};var per2 = new Object;per2.name = "不寫代碼的碼農";
屬性操作

在JavaScript中,可以隨時為對象添加屬性:

per1.age = 0;per1.sayName = function(){    alert(this.name);   //"Pomy"}

因而,在檢測對象屬性是否存在時,常犯的一個錯誤是:

//結果是falseif(per1.age){    alert(true)}else{    alert(false);}

per1.age 是存在的,但是其值是0,所以不能滿足if條件。if判斷中的值是一個對象、非Null 字元串、非零數字或true時,判斷會評估為真;而當值是一個null、undefined、0、false、NaN或Null 字元串時評估為假。
因而,檢測屬性是否存在時,有另外的兩種方式:in和hasOwnProperty(),前者會檢測原型屬性和自有(執行個體)屬性,後者只檢測自有(執行個體)屬性。

console.log("age" in per1);  //trueconsole.log(per1.hasOwnProperty("age"));  //trueconsole.log("toString" in per1);  //trueconsole.log(per1.hasOwnProperty("toString"));  //false

對象per1並沒有定義toString,該屬性繼承於Object.prototype,所以in和hasOwnProperty()檢測該屬性時出現差異。如果只想判斷一個對象屬性是不是原型,可以利用如下方法:

function isPrototypeProperty(obj,name){    return name in obj && !obj.hasOwnProperty(name);}

若要刪除一個屬性,用delete操作符,用於刪除自有屬性,不能刪除原型屬性。

per1.toString = function(){    console.log("per1對象");};console.log(per1.hasOwnProperty("toString"));   //trueper1.toString();   //"per1對象"delete per1.toString;console.log(per1.hasOwnProperty("toString"));   //falseconsole.log(per1.toString());  //[object Object]

有時需要枚舉對象的可枚舉屬性,也有兩種方式:for-in迴圈和Object.keys(),前者依舊會遍曆出原型屬性,後者只返回自有屬性。所有可枚舉屬性的內部屬性[[Enumerable]]的值均為true。

var per3 = {    name:"Pomy",    blog:"http://www.ido321.com",    age:22,    getAge:function(){        return this.age;    }};

實際上,大部分原生屬性的[[Enumerable]]的值均為false,即該屬性不能枚舉。可以通過propertyIsEnumerable()檢測屬性是否可以枚舉:

console.log(per3.propertyIsEnumerable("name"));  //truevar pros = Object.keys(per3);  //返回可枚舉屬性的名字數組console.log("length" in pros);  //trueconsole.log(pros.propertyIsEnumerable("length"));  //false

屬性name是自訂的,可枚舉;屬性length是Array.prototype的內建屬性,不可枚舉。

屬性類型

屬性有兩種類型:資料屬性和訪問器屬性。二者均具有四個屬性特徵:

資料屬性:[[Enumerable]]、[[Configurable]]、[[Value]]和[[Writable]] 訪問器屬性:[[Enumerable]]、[[Configurable]]、[[Get]]和[[Set]]

[[Enumerable]] :布爾值,屬性是否可枚舉,自訂屬性預設是true。
[[Configurable]] :布爾值,屬性是否可配置(可修改或可刪除),自訂屬性預設是true。它是無法復原的,即設定成false後,再設定成true會報錯。
[[Value]]:儲存屬性的值。
[[Writable]]:布爾值,屬性是否可寫,所有屬性預設可寫。
[[Get]]:擷取屬性值。
[[Set]]:設定屬性值。
ES 5提供了兩個方法用於設定這些內部屬性:
Object.defineProperty(obj,pro,desc_map) 和 Object.defineProperties(obj,pro_map)。利用這兩個方法為per3添加一個屬性和建立一個新對象per4:

Object.defineProperty(per3,"sex",{    value:"male",    enumerable:false,    configurable:false, //屬性不能刪除和修改,該值也不能被設定成true});console.log(per3.sex);  //'male'console.log(per3.propertyIsEnumerable("sex"));  //falsedelete per3.sex;    //不能刪除per3.sex = "female"; //不能修改console.log(per3.sex);  //'male'Object.defineProperty(per3,"sex",{    configurable:true, //報錯});per4 = {};Object.defineProperties(per4,{    name:{        value:"dwqs",        writable:true    },    blog:{        value:"http://blog.92fenxiang.com"    },    Name:{        get:function(){            return this.name;        },        set:function(value){            this.name = value;        },        enumerable:true,        configurable:true    }});console.log(per4.name); //dwqsper4.Name = "Pomy";console.log(per4.Name); //Pomy

需要注意的是,通過這兩種方式來定義新屬性時,如果不指定特徵值,則預設是false,也不能建立同時具有資料特徵和訪問器特徵的屬性。可以通過Object.getOwnPropertyDescriptor()方法來擷取屬性特徵的描述,接受兩個參數:對象和屬性名稱。若屬性存在,則返回屬性描述對象。

var desc = Object.getOwnPropertyDescriptor(per4,"name");console.log(desc.enumerable); //falseconsole.log(desc.configurable); //falseconsole.log(desc.writable); //true

根據屬性的屬性類型,返回的屬性描述對象包含其對應的四個屬性特徵。

禁止修改對象

對象和屬性一樣具有指導其行為的內部特徵。其中,[[Extensible]]是一個布爾值,指明改對象本身是否可以被修改([[Extensible]]值為true)。建立的對象預設都是可以擴充的,可以隨時添加新的屬性。
ES5提供了三種方式:

Object.preventExtensions(obj):建立不可擴充的obj對象,可以利用Object.isExtensible(obj)來檢測obj是否可以擴充。strict 模式下給不擴充項物件添加屬性會報錯,非strict 模式下則添加失敗。 Object.seal(obj):封印對象,此時obj的屬性變成唯讀,不能添加、改變或刪除屬性(所有屬性都不可配置),其[[Extensible]]值為false,[[Configurable]]值為false。可以利用Object.isSealed(obj)來檢測obj是否被封印。 Object.freeze(obj):凍結對象,不能在凍結對象上添加或刪除屬性,不能改變屬性類型,也不能寫入任何資料類型。可以利用Object.isFrozen(obj)來檢測obj是否被凍結。

注意:凍結對象和封印對象均要在strict 模式下使用。

"use strict";var per5 = {    name:"Pomy"};console.log(Object.isExtensible(per5));   //trueconsole.log(Object.isSealed(per5));         //falseconsole.log(Object.isFrozen(per5));       //falseObject.freeze(per5);console.log(Object.isExtensible(per5));   //falseconsole.log(Object.isSealed(per5));       //trueconsole.log(Object.isFrozen(per5));       //trueper5.name="dwqs";console.log(per5.name);   //"Pomy"per5.Hi = function(){    console.log("Hi");};console.log("Hi" in per5);  //falsedelete per5.name;console.log(per5.name);  //"Pomy"var desc = Object.getOwnPropertyDescriptor(per5,"name");console.log(desc.configurable);  //falseconsole.log(desc.writable);  //false

注意,禁止修改對象的三個方法只對對象的自有屬性有效,對原型對象的屬性無效,仍然可以在原型上添加或修改屬性。

function Person(name){    this.name = name;}var person1 = new Person("Pomy");var person2 = new Person("dwqs");Object.freeze(person1);Person.prototype.Hi = function(){    console.log("Hi");};person1.Hi();  //"Hi";person2.Hi();  //"Hi";

原文:http://www.ido321.com/1585.html

相關文章:
DOM筆記(九):參考型別、基本封裝類型和單體內建對象
DOM筆記(十一):JavaScript對象的基本認識和建立

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.