js 深刻 —— 從數據類型到原型鏈

1、數據類型

javascript中的數據類型能夠分爲兩種類型, 基本數據類型引用數據類型。其中基本數據類型包括 String, Number, Boolean, null, undefined, Symbol(ES6)六大數據類型,引用數據類型 object
  1. 一般,數值、字符串、布爾值這三種類型,合稱爲原始類型,
  2. 對象則稱爲合成類型(complex type)的值,由於一個對象每每是多個原始類型的值的合成,能夠看做是一個存放各類值的容器。
  3. 至於undefined和null,通常將它們當作兩個特殊值。
這裏所講的合成類型object,其實式一個廣義的對象,他包括三個子類型,[ 狹義的對象arrayfunction]

咱們通常所說的對象都是狹義的對象。javascript

基本數據類型是按照值進行分配的,是存放在了棧內存的數據片斷,能夠直接訪問到。引用數據類型則是存放在堆內存中的數據,例如: var a = {}; a只是存儲了{}的指針,這個指針指向了內存的地址。java

檢測數據類型web

javascript中可使用typeof操做符來判斷數據類型。可是typeof null = object; 這是歷史遺留的bug;數組

typeof 123;               // "number"
typeof "hfhan";           // "string"
typeof true;              // "boolean"
typeof null;              // "object"  獨一份的不同凡響
typeof undefined;         // "undefined"
typeof Symbol("hfhan");   // "symbol"
typeof function(){};      // "function"   // 這裏不是object哦~~~
typeof {};                // "object"
typeof window             // "object"
typeof {}                 // "object"
typeof []                 // "object"

null是一個表示「空」的對象,轉爲數值時爲0undefined是一個表示」此處無定義」的原始值,轉爲數值時爲NaNpromise

null和undefined的用法於含義

null表示空值,即該處的值如今爲空。調用函數時,某個參數未設置任何值,這時就能夠傳入null,表示該參數爲空。好比,某個函數接受引擎拋出的錯誤做爲參數,若是運行過程當中未出錯,那麼這個參數就會傳入null,表示未發生錯誤。瀏覽器

undefined表示「未定義」,下面是返回undefined的典型場景。app

// 變量聲明瞭,但沒有賦值
var i;
i // undefined

// 調用函數時,應該提供的參數沒有提供,該參數等於 undefined
function f(x) {
  return x;
}
f() // undefined

// 對象沒有賦值的屬性
var  o = new Object();
o.p // undefined

// 函數沒有返回值時,默認返回 undefined
function f() {}
f() // undefined
能夠轉換爲false的值
undefined
null
false
0
NaN
""或''(空字符串)

2、對象類型

宿主環境函數

通常宿主環境由外殼程序建立於維護,只要是可以提供js引擎執行環境都稱爲是外殼程序。如:web 瀏覽器, 桌面應用程序等。大數據

即由web瀏覽器、桌面應用程序等的外殼程序所造就的環境就是宿主環境this

js對象的分類

js的對象能夠分爲三類:內部對象 宿主對象 自定義對象

1. 內部對象

1.1 本地對象

ECMA-262把本地對象定義爲是: 獨立於宿主環境的ECMASCRIPT實現所提供的對象。

本地對象包含Object Function Boolean String Array Date RegExp Number 以及各種錯誤對象(Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError

1.2 內置對象

ECMA-262把內置對象定義爲是: 由 ECMAScript 實現提供的、獨立於宿主環境的全部對象,在 ECMAScript 程序開始執行時出現。意味着你不須要明確實例化就能夠是直接使用。

包括由 Global Math兩個內置對象。

global

global對象算是一個比較特殊的對象了吧,由於無論你從哪一個角度看,它都是不存在的。全局做用域下的一些屬性和方法好比: isNaN parseInt等。都是global的屬性和方法。
JavaScript 全局對象參考手冊

2. 宿主對象

宿主對象就是執行JS腳本的環境提供的對象。對於嵌入到網頁中的JS來講,其宿主對象就是瀏覽器提供的對象,因此又稱爲瀏覽器對象(BOM)

不一樣的瀏覽器提供的宿主對象可能不一樣,即便提供的對象相同,其實現方式也截然不同!這會帶來瀏覽器兼容問題,增長開發難度。

瀏覽器對象有不少,如WindowDocument等等。

對於web瀏覽器而言, Global有一個代言人 window,可是window並非ECMAScripta規定的內置對象,由於window對象是相對於web瀏覽器而言的,而js不只僅能夠用在瀏覽器中。

document對象是window對象的一個屬性,是顯示於窗口內的一個文檔。而window對象則是一個頂層對象,它不是另外一個對象的屬性。document能夠理解爲文檔,就是你的網頁,而window是你的窗口,就是你的瀏覽器打開所顯示的哪一個窗口。

3. 自定義對象

顧名思義,就是開發人員本身定義的對象。JavaScrip容許使用自定義對象,使JavaScript應用及功能獲得擴充


3、判斷對象的類型

使用Object.prototype.toString()來判斷。

Object.prototype.toString.apply(new Function); // "[object Function]"
Object.prototype.toString.apply(new Object);       // "[object Object]"
Object.prototype.toString.apply(new Date);         // "[object Date]"
Object.prototype.toString.apply(new Array);        // "[object Array]"
Object.prototype.toString.apply(new RegExp);       // "[object RegExp]"
Object.prototype.toString.apply(new ArrayBuffer);  // "[object ArrayBuffer]"
Object.prototype.toString.apply(Math);             // "[object Math]"
Object.prototype.toString.apply(JSON);             // "[object JSON]"
var promise = new Promise(function(resolve, reject) {
    resolve();
});
Object.prototype.toString.apply(promise);          // "[object Promise]"

下面正式進入咱們的正題

4、構造函數

在javascript中對象的建立有兩種方式,對象字面量構造函數

4.1 對象字面量

var o1 = {  
    p:」I’m in Object literal」,  
    alertP:function(){  
        alert(this.p);  
    }  
}  
// 這種寫法不須要定義構造函數,所以不在本文的討論範圍以內。這種寫法的缺點是,每建立一個新的對象都須要寫出完整的定義語句,不便於建立大量相同類型的對象,不利於使用繼承等高級特性。

4.2 構造函數(構造器)

new表達式是配合構造函數使用,能夠實現更好的效果

new String(「a string」)
// 調用內置的String()方法來構建了一個字符串對象。



function CO(){  
    this.p = 「I’m in constructed object」;  
    this.alertP = function(){  
        alert(this.p);  
    }  
}  
var o2 = new CO();
針對new操做符號在調用構造函數,咱們來刨析一下具體發生了什麼

發生了四件事

var obj = {}; // 第一步建立一個空對象
obj.__proto__ = CO.prototype; // 讓空對象的成員指向構造函數的prototype成員對象
CO.call(obj); // 第三步,將構造函數的做用域賦值給新的對象
return obj; // 返回新的對象
  • 注意
function C2(a, b){  
    this.p = a + b;  
    this.alertP = function(){  
        alert(this.p);  
    }  
    return this.p;//此返回語句在C2做爲構造函數時沒有意義  
}  
var c2 = new C2(2,3);  
c2.alertP();//結果爲5  
alert(C2(2, 3)); //結果爲5  

// 該實例是可行的,可是不推薦哦,
// 該函數既能夠用做構造函數來構造一個對象,也能夠做爲普通的函數來使用。用做普通函數時,它接收兩個參數,並返回二者的相加的結果。爲了代碼的可讀性和可維護性,建議做爲構造函數的函數不要摻雜除構造做用之外的代碼;一樣的,通常的功能函數也不要用做構造對象。

以上兩種方式中展示的都是咱們自定義的對象,看了兩種建立對象對的方式,咱們來結合內部對象來繼續分析:

4.3 普通建立法

一個函數能夠經過下面的方式直接建立。

function a(){

}

建立一個對象例如是object 能夠是 {} ,建立數組能夠是[], 建立正則能夠是/.*/

4.4 構造函數建立對象

var a = new Function(){

}
var b = new Object({a:1})
var c = new Array(10)
var d = new Date()
var e = new Set()

咱們直接(new)使用內部對象的構造函數就能夠建立一個對象了。

// 除了內置的一些對象以外,咱們還可使用普通的函數來構建對象。

function person (){
}

var p1 = new Person();
  • 咱們約定普通函數以小寫字母開頭,構造函數以大寫字母開頭。

5、原型以及原型鏈

未完待續
相關文章
相關標籤/搜索