前言
javaScript門檻非常低,一點語法,一個dom,一個bom就可以使用它開發大部分js應用,再加上現在層出不窮的框架極大的簡化抽象了javaScript的使用方式,但是我們始終不能忘記的一點是,決定上層建築的,是經濟基礎。 決定你的javaScript能走多遠的,是基礎。所以我決定在我的博客開一個關於javaScript基礎系列。詳細得,解讀其中的基礎,再次刨開它的心臟細細研究。與大家共勉。
第一篇 字符串一
我們從字符串開始介紹。
字符串(String) 基礎概念:一串有意義的字符集合叫做字符串,在js中使用單引號‘string’ 或者雙引號 "string"表示字符串。它是js五個基本類型之一,姑且可以認為它是js基本類型中特性最多的,技巧最多的基本類型。其他的如Number、boolean、null、undefined,其使用方式,引用方法,概念都沒有字符串來得多。
了解js中的字符串的使用原理
一、字符串的表達形式。
① 通過字面表達式定義的字符串。
1 var str = "這是一串字符串";
聲明了一個變量str ,給這個變量指定值字符串 “”;
②通過js內置的String構造函數,
1 /***************************** 2 通過構造函數定義的字符串, 3 實際上可以叫做字符串對象, 4 在chorme中返回一個字符拆分的對象 5 */ 6 var str = new String("hello world"); 7 console.log(str);
二、字符串與字符串對象(為什么普通字符串可以調用構造函數的方法?)。
通過字面表達式定義的字符串與通過js內置的String構造函數生成的字符串,它們在使用的時候,行為似乎是一致的,但是,在更正確的表達中,它們是不同的,通過字面表達式我們直接給變量賦予了一個字符串值,而通過構造函數,我們得到的是一個String對象。
下圖是內置的String構造函數在chorme中返回一個字符拆分的對象:
而字面量方式則是:
通過對兩個方式的typeof對比,我們可以看到:
/***************************** 通過構造函數定義的字符串, 實際上可以叫做字符串對象, 在chorme中返回一個字符拆分的對象 */ var str = new String("hello world"); console.log(str); //上圖1 /***************************** 通過typeof檢查的字符串對象,返回了object */ var _type = typeof str; console.log(_type) //object /***************************** 不使用構造函數,直接賦值呢? 它就是一個基本值, typeOf返回string */ var str1 = "hello world"; console.log(str1); //上圖2 var _type1 = typeof str1; console.log(_type1) //string
它們是否相等?答案是不相等,
console.log(str === str1); //false
那么我可以這么簡單的理解:new操作符只會返回對象,new String()永遠都是一個對象,而對象是不會和字符串相等的。
有一點經驗的同學應該可以看出,這里如果使用==的話,str==str1,返回的是true。這是因為js中的類型轉換機制決定的,它隱式的調用了字符串對象的valueOf方法。我們可以做一個小實驗:
/*************************** 如果我重寫str的valueOf方法將它指向一個新的值 */ console.log("before ",str == str1);//true str.__proto__.valueOf = function(){ return "javaScript!"; } console.log("after ",str == str1);//false
console.log(str+str1) //javaScript!hello world
我更改了str的原形對象中的valueOf方法,使它總是返回一個新字符值 "javaScript!",最后再和str1用==比對的時候,返回了false。
目前為止可以得出結論是,字符串和字符串對象不相等,甚至不是同一個概念,一個是基本類型值,一個是構造函數生成的字符對象,但在js機制中,比較時隱式的使用了valueOf方法,調用拼接時也隱式調用了valueOf方法。
js以這種方式給字符串“繼承”了一些方法,能看到的做法是,js在使用字面表達式定義的字符串調用方法時,悄悄的給它包了一層字符串對象的殼。
通過調用__proto__屬性就可以看出
//通過調用__proto__屬性就可以看出 console.log(str1.__proto__ === str.__proto__); //true 他們繼承的對象是相等的
字符串與字符串對象的使用方式一致,typeof得到的值不同,在使用字面表達式定義的字符串調用方法時,js會隱式調用new String(),這就是為什么基礎類型能夠調用對象方法的原因。
通過這個理解方式,我們就不難理解為什么一個數字、一個字符串能調用內置方法了。
三、字符串下標
字符串是有下標的。由於上面介紹的字符串與字符串對象的關系,任意字符串都可以通過下標訪問到對應的位置的單個字符。下圖在chorme中打印的一個字符串對象:
可以看到一共11個字符從0到10,需要注意的是它並不是數組。而是一個屬性名為0-10的對象。
/***************************** 可以通過下標訪問字符串字符 這里字符串對象和字符串同樣能使用下標訪問, 這是因為javascript編譯時,會在適當的時候將字符串包裝成字符串對象, 這樣一般的字符串就也可以調用String構造函數的方法了 */ console.log(str[0]); //h console.log(str1[0]); //h
我們可以, 通過for循環打印每一個字符,也可以,通過數組的方法借用將字符串轉換成數組:
Array.prototype.slice.call(str) //["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
但是需要注意的是,如果你直接修改str[11] = "!"的話,只會在對象中新增了一個名為11的屬性,並不會修改到字符串本身的值。
str[11] = "!"; console.log(str.valueOf()) // hello world 修改失敗!
為什么js要這么干?將字符串存儲兩份,一份是一個一個的對象屬性字符集,另一份指向原始值,也就是上圖的 [[PrimitiveValue]].。
我覺得它們有一個先后關系,先生成一個一個的對象屬性,再由對象屬性的一個個字符拼接成 [[PrimitiveValue]];
單元總結
真正的基礎是什么?我覺得是它的內在原理,它的實現思路以及實現方式,所以文中並沒有給出更多的字符串操作方法,
本章介紹了字符串調用方法的來歷,介紹了字符串下標的原理。下一章講什么,待定,博主是一邊回顧基礎,一邊理解,一邊寫博客,當然也有很多不正確的地方,感謝大家包容,更感謝大家指正。
最后
==============================================================================================
一首詩
我想寫一首詩,
歌頌風,
頌唱雨。
只是,
我的桌子上沒有一支筆,
詩沒有筆可能代表着,
也許遠方不那么遠,
它就在筆上飛揚。
================================================================================================
轉載請注明出處。 9月12日划水的下午