Javascript基礎(chǔ)回顧之(一) 類型
本來是要繼續(xù)由淺入深表達(dá)式系列最后一篇的,但是最近團(tuán)隊(duì)突然就忙起來了,從來沒有過的忙!不過喜歡表達(dá)式的朋友請(qǐng)放心,已經(jīng)在寫了:) 在工作當(dāng)中發(fā)現(xiàn)大家對(duì)Javascript的一些基本原理普遍存在這里或者那里的一知半解,所以決定先花一些時(shí)間整理一下這些基礎(chǔ)知識(shí)和大家分享。 剛開始是打算寫一篇的,但是后來寫著寫著就發(fā)現(xiàn)越來越多,所以決定還是寫一個(gè)系列吧。本系列所有內(nèi)容都是涉及Javascript基礎(chǔ)的,沒有時(shí)髦的玩意兒,但是我相信這些基礎(chǔ)的東西會(huì)有助于你理解那些有趣的東西的。
是的,說到Javascript我能想到的就是有趣,好玩!那么到底哪些地方好玩,為什么好玩呢?我們一起來玩玩吧,讓我們玩著玩著就把Javascript理解透徹了。本文所包括的內(nèi)容:
基本類型
Object 與 object
基本包裝類型
值類型和引用類型
function類型
基本類型
Javascript有5種基本數(shù)據(jù)類型(也叫簡(jiǎn)單數(shù)據(jù)類型):Undefined、Null、Boolean、Number、String 和1種復(fù)雜數(shù)據(jù)類型Object。
var undefinedVariable;
var nullValue = null;
var cnblogs = new Object();
var func = function () { };
typeof ("string");
typeof (100);
typeof (true);
typeof (undefinedVariable);
typeof (cnblogs);
typeof (undeclaredValue);
typeof (nullValue);
typeof (null)
typeof (func)
告訴我結(jié)果是什么?


好玩之一: 聲明但未賦值 和 未聲明的變量都是 undefined
好玩之二: 只有聲明并賦值為null,它的值才會(huì)null
好玩之三: typeof(Object) 竟然是一個(gè)function
好玩之四: typeof(null) 竟然是一個(gè)object
Null 和Undefined這兩種類型都只有一個(gè)值,即null和undefined。從邏輯上看null值表示一個(gè)空對(duì)象的指針,這就是為什么typeof(null)會(huì)返回Object。 并且undefined是派生自null值的,所以......
好玩之五: null == undefined 是成立的。
但是想一想,Null和Undefined畢竟是兩種不同的類型,即使他們是父類和子類的關(guān)系,在C#里面父類和子類也不能相等啊,不是么?其實(shí)null == undefined就是硬性規(guī)定,ECMA規(guī)定它們做相等性測(cè)試的時(shí)候要返回true所以他們返回true了。就好像我們?cè)贑#里面重寫了equlas 方法一樣。
至于為什么 typeof(Object) 返回 function,請(qǐng)看下面的Object與object。
Object 與 object
Javascript高級(jí)程序一書中說到 ”函數(shù)在ECMAScript中是對(duì)象,不是一種數(shù)據(jù)類型”。 好像是譯者加上去的,既然typeof(Object) 都返回 function了,為什么還說function不是一種數(shù)據(jù)類型呢?Object 和 function之間是什么關(guān)系呢?
在我看來,Object其實(shí)就是一個(gè)function,或者我們說Object是一個(gè)函數(shù)的名字比較容易理解,官方名稱是構(gòu)造函數(shù)。
var p = new Object();
p.name = "jesse";
p.age = 18;
function Person(name,age)
{
this.name = name;
this.age = age;
}
var p2 = new Person("jesse", 18);
在上面的代碼中, 如果我們把Object當(dāng)作一個(gè)函數(shù)名那么 new Object() 和 new Person() 性質(zhì)就是一樣的了。通過 new 操作符得到一個(gè) function 實(shí)例, 這里面的function就已經(jīng)是類的概念了。所以這里的Object其實(shí)是一個(gè)function。這樣我們就可以解釋為什么typeof(Object)是function了。
那我們?cè)谏厦嫠f的復(fù)雜類型Object,它又是什么呢?

Object是function,但是 new Object() 則是 object。到這里面就搞清楚了首字母大寫的這個(gè)Object是一個(gè)function,而首字母小寫的這個(gè)object它才是一種數(shù)據(jù)類型。所以我建議大家以后說到類型的時(shí)候全部用小寫,我們的基本類型是 string, number, boolean。大寫的String, Number, Boolean 它們只是一個(gè)函數(shù)而已。而調(diào)用這些函數(shù)所得到的結(jié)果是,沒錯(cuò),是object。

最后,我們是找不到Undefined 和Null 這兩個(gè)函數(shù)的,所以這兩種數(shù)據(jù)類型就是undefined和null(為什么typeof(null)會(huì)得到object已經(jīng)說了)

好玩之六: Object 不是object類型
基本包裝類型
我們上面講了string, number, boolean是基本類型,基本類型和復(fù)雜類型最大的區(qū)別就是基本類型沒有prototype屬性。也就意味著你不能給基本類型隨意的添加方法或?qū)傩浴?/p>
var str = "str"; // typeof(str): string
var strObj = new String("str"); // typeof(strObj):object
strObj.name = "strObj";
strObj.alert = function () {
alert(this.name);
};
strObj.alert(); // strObj
str.name = "str"; //wrong...
str.alert = function () {
alert(this);
}
str.alert(); // this is wrong.... nothing is gonna happen.
同時(shí)我們還說到了首字母大寫的這個(gè)String是一個(gè)function,所以new String("str")得到的是一個(gè)object而不是一個(gè)string,這里大家要搞清楚了。我們的問題來了,為什么基本類型string會(huì)有一些初始的方法呢?它不是基本類型么?方法是怎么加上去的?
str = str.concat("str2");
strObj = strObj.concat("str2");
strObj.alert(); //之后返回 string 不再是一個(gè)對(duì)象了, 所以這里也不再有alert方法了。
str是string類型的變量,記住它不是一個(gè)對(duì)象。它是不應(yīng)該有方法的,那么它的contact方法從何而來呢?這里后臺(tái)在調(diào)用str.contact的時(shí)候?qū)嶋H上偷偷的完成了幾步操作:
- 基于str創(chuàng)建一個(gè)String類型的實(shí)例
- 在實(shí)例上調(diào)用指定的方法
- 銷毀這個(gè)實(shí)例
將這三個(gè)步驟想象成這樣:
var str2 = new String(str);
str = str2.concat("str2");
str2= null;
我們可以把String,Number,Boolean叫做封裝類型, 他們就好像我們?cè)贑#里面的自定義類型一樣。 但是不要忘記了我們真正的基本類型是string, number, boolean。用String所構(gòu)造出來的對(duì)象是屬于object類型的。
好玩之七: String 不是 string
值類型和引用類型
我們上面講到了5種基本類型:string, number, boolean, null, undefined 全部是值類型。Javascript中只有一種引用類型,也就是我們的復(fù)雜類型object。那么有人可能會(huì)好奇,那么像Date, Regex, Arrary這些是什么類型呢 ? 其實(shí)這里面的概念有一點(diǎn)混淆,如果你很好的理解了上面的Object 和object之間的區(qū)別,可能會(huì)比較好理解一點(diǎn)。 我們可以把function 看成是C#里面 class關(guān)鍵字,我們可以用class定義類,同樣我們可以在Javascript中用function來定義類。
在C#中定義類:
namespace ConsoleApplication1
{
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
var p =new Person();
Console.WriteLine(p.GetType()); // ConsoleApplication1.Person
Console.ReadLine();
}
}
}
在Javascript定義類:
function Person(name,age)
{
this.name = name;
this.age = age;
}
var p = new Person();
typeof(p); //object
你發(fā)現(xiàn)區(qū)別了么?如果我們?cè)贘avascript中用function定義類,他們的實(shí)例將永遠(yuǎn)是object, 包括原生的那些Date, Array, RegExp。
typeof (new Date()); // object typeof (new Array()); // object typeof (new RegExp()); // object

好玩之八: 全部都是object
如果全部都是object的話,那我怎么能知道這個(gè)對(duì)象到底是不是Date或者Person的實(shí)例呢?借助于instanceof 就可以了。

終級(jí)好玩:我用function創(chuàng)建了一個(gè)Person類,然后用new得到一個(gè)Person的實(shí)例,結(jié)果它卻不是Person類型的。 這就好像生了個(gè)孩子,供他吃穿,但是他卻不跟你姓,這得有多么無私偉大才干得出來的事啊!
function類型
function類型有兩種,函數(shù)聲明和函數(shù)表達(dá)式。函數(shù)聲明具有優(yōu)先級(jí),可以在聲明之前被使用,表達(dá)式卻不能。
sayGoodNight(); // right
sayHello(); // wrong
var sayHello = function (name) {
alert("Hello, " + name);
};
function sayGoodNight(Name) {
alert("Good Night, "+ name);
}
除此之外,函數(shù)表達(dá)式還可以像object一樣,隨意的添加屬性。
var sayHello = function (name) {
alert("Hello, " + name);
};
sayHello.age = 18;
sayHello.sayAge = function () {
alert("I am" + 18) ;
}
sayHello.sayAge(); // I am 18
但是,函數(shù)表達(dá)式到底是個(gè)什么玩意兒呢? 不能實(shí)例化,但是可以隨意的添加屬性,它和object有什么區(qū)別?我們?cè)谏厦嬲f過,object其實(shí)就是一個(gè)對(duì)象實(shí)例。
我們還有大寫的Function, 它和function之間的關(guān)系會(huì)不會(huì)和String 和string 一樣?( 以下內(nèi)容比較費(fèi)腦力,慎入!)
var sayHello = new Function('name','alert("My name is " + name );');
sayHello('Jesse');
sayHello instanceof Function; // true
var sayHello2 = function (name) {
alert('My name is' + name);
};
sayHello2 instanceof Function; // true
我們上面調(diào)用Function去構(gòu)造了一個(gè)函數(shù)。既沒有用函數(shù)聲明,也沒有用函數(shù)表達(dá)式,不管怎么說這是第三種創(chuàng)建函數(shù)的方法,雖然肯定沒有多少人用它,因?yàn)樗还苁菂?shù),還是函數(shù)體全部都是字符串,這寫起來還不讓人崩潰么?


看出什么貓膩來了么?所謂的函數(shù)表達(dá)式,其實(shí)是用一個(gè)變量接收了一個(gè)function的對(duì)象而已。而這個(gè)function的對(duì)象則是Function的實(shí)例。包括用函數(shù)聲明寫出來的函數(shù)也是Function的實(shí)例。
function sayHello3(name)
{
alert('My name is' + name);
}
sayHello3 instanceof Function; // true
但是,等等,我們前面說到的String, Date, Array都是function類型的,那Function也是么?

我們前面說所有function的實(shí)例都是object類型的,但是對(duì)于Function 這個(gè)奇異的function來說,它的實(shí)例仍然是function類型的,并且我們可以用Function的實(shí)例再創(chuàng)造實(shí)例。原來我們所說的用function創(chuàng)造出來的類,它不是類,而是Function的實(shí)例。
function Person(name) {
this.name = name;
}
Person instanceof Function; // true
我們?cè)俳Y(jié)合自執(zhí)行函數(shù)理解一下,也許會(huì)好一點(diǎn):
(function () {
alert("something...");
}());
實(shí)際上我們上面的function(){} 會(huì)返回給我們一個(gè)function的實(shí)例,那么我們當(dāng)然可以直接執(zhí)行它了。這么看來function應(yīng)該是Javascript里面最特別的類型了。
好玩之十:所有的function都是Function的實(shí)例
好玩之十一:Function 本身也是一個(gè)function

最后我們來總結(jié)一下:
- Javascript中有5種基本類型:string, number, boolean, null, undefined。
- 另外一種復(fù)雜類型object 其實(shí)是function的實(shí)例。
- 除了Function這個(gè)系統(tǒng)里面的function構(gòu)造器以外,其它所有function的實(shí)例都是object類型的。
- Date, Array, RegExp 這些都是function類型,同時(shí)也是Function的實(shí)例。同理,它們的實(shí)例也是object類型的。
總結(jié)完了,好像也不多,不是么?關(guān)于function其實(shí)javascript是非常強(qiáng)大的一個(gè)功能,作用域以及面向?qū)ο蟮囊恍┲R(shí)也是和它息息相關(guān)的,我們下一篇就來看看作用域的問題。謝謝大家的關(guān)注!
- Javascript中數(shù)組去重與拍平的方法示例
- 理解javascript中的Function.prototype.bind的方法
- JavaScript數(shù)組復(fù)制詳解
- Javascript基礎(chǔ)回顧之(三) js面向?qū)ο?/a>
- JavaScript基礎(chǔ)之AJAX簡(jiǎn)單的小demo
- JavaScript Date 知識(shí)淺析
- JavaScript實(shí)現(xiàn)時(shí)鐘滴答聲效果
- Javascript中 帶名 匿名 箭頭函數(shù)的重要區(qū)別(推薦)
- javascript判斷回文數(shù)詳解及實(shí)現(xiàn)代碼
- 淺談javascript中的 “ && ” 和 “ || ”
- Javascript中的 “&” 和 “|” 詳解
相關(guān)文章
caller和callee的區(qū)別介紹及演示結(jié)果
caller返回一個(gè)函數(shù)的引用,這個(gè)函數(shù)調(diào)用了當(dāng)前的函數(shù);callee放回正在執(zhí)行的函數(shù)本身的引用,它是arguments的一個(gè)屬性,感興趣的你可以參考下或許可以幫助到你2013-03-03
javascript Event對(duì)象詳解及使用示例
Event代表事件狀態(tài),如事件發(fā)生的元素,鍵盤狀態(tài),鼠標(biāo)位置和鼠標(biāo)按鈕狀態(tài),event對(duì)象只在事件發(fā)生的過程中才有效,本文整理了一些,喜歡的朋友可以學(xué)習(xí)下2013-11-11
詳解Javascript函數(shù)聲明與遞歸調(diào)用
本篇文章詳細(xì)的介紹了Javascript函數(shù)聲明與遞歸調(diào)用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下。2016-10-10
JavaScript中this用法學(xué)習(xí)筆記
在本篇文章里小編給大家分享了關(guān)于JavaScript中this用法學(xué)習(xí)筆記以及知識(shí)點(diǎn)總結(jié),有興趣的朋友們學(xué)習(xí)下。2019-03-03
javascript的數(shù)組和常用函數(shù)詳解
這篇文章主要介紹了javascript的數(shù)組和常用函數(shù)詳解,非常詳細(xì),適合新手學(xué)習(xí),需要的朋友可以參考下2014-05-05
javascript中的throttle和debounce淺析
這篇文章主要介紹了javascript中的throttle和debounce淺析,分別介紹了throttle和debounce的使用場(chǎng)景及具體案例,需要的朋友可以參考下2014-06-06
Javascript & DHTML 實(shí)例編程(教程)(三)初級(jí)實(shí)例篇1—上傳文件控件實(shí)例
Javascript & DHTML 實(shí)例編程(教程)(三)初級(jí)實(shí)例篇1—上傳文件控件實(shí)例...2007-06-06

