摘要:前言由于最近的項目用到了一些的代碼,所以我帶著好奇心,認真閱讀了這本書,粗略地了解語言的基本結構和特性,對于一些不熟悉的新概念,以記錄的形式加強印象,也是對學習的反思總結。
前言
由于最近的項目用到了一些js的代碼,所以我帶著好奇心,認真閱讀了這本書,粗略地了解js語言的基本結構和特性,對于一些不熟悉的新概念,以記錄的形式加強印象,也是對學習的反思總結。
一、字面量(literals)“字面量“這個詞在書中高頻出現,先看看他的定義:
字面量表示如何表達這個值,一般除去表達式,給變量賦值時,等號右邊都可以認為是字面量。
舉個簡單的例子就明白了,例如
var a = 1; var b = "hello world"; var c = []; var d = {}; var e = function (a,b){return a + b;}
以上例子中,賦值號右邊都是字面量,分別是數字字面量,字符串字面量,數組字面量,對象字面量及函數字面量。
為什么要有字面量呢?我的理解,js和php一樣都是弱類型語言,需要根據賦值號右邊的內容來判斷變量的類型,而字面量就是為了很方便地按照指定規格創建新的對象,數組或者定義函數值,讓我們更清楚地知道我到底定義了一個什么。
字面量與變量的區別?字面量都是一些不可改變的值,比如 :1 2 3 4 5
變量就像一個容器,可以用來保存字面量,而且變量的值是可以任意改變的
通常我們不會直接調用字面量,而是先將字面量存到變量中,再進行調用
二、對象(object)真的應了老師說的,”萬物皆對象“,在js中,沒有類,有的只有對象,數組是對象,函數是對象,正則表達式是對象,當然,對象也是對象。
對象字面量(object literals)寫法很簡單,就是一對花括號括住“屬性:值”對,這里就不再舉例子了,對象是可以嵌套的,用點運算符來獲取對象的某個值
引用(reference)對象不會復制,通過引用來傳遞,例如
var stooge = { name : "Jack"; }; var x = stooge; x.name = "Tom"; var result = stooge.name;
由于x與stooge指向同一個對象,所以此時result為”Tom“.
原型(prototype)js里,每一個對象都會連接一個原型對象,并且可以繼承屬性,所有通過字面量對象創建的對象都會連接到Object.prototype,它是js中標配對象
當創建一個對象時,可以選擇一個對象作為它的原型,,這有點像類的繼承,具體實現的方法書中已經幫我們寫好了,直接拿來套用就行
var stooge = { name : "Tom" }; if (typeof Object.beget !== "function") { Object.create = function(o){ var F = function () {}; F.prototype = o; return new F(); }; } var another_stooge = Object.create(stooge);//another_stooge選擇stooge作為它的原型
關于原型,有幾點需要注意
對一個對象做出改變時,不影響它的原型,但改變原型的屬性時,繼承它的對象的屬性也會改變,但不會改變繼承以后新增的屬性
在原型之中添加屬性,繼承它的所有對象也會可見,改變原型的一個屬性,繼承它的對象的屬性也會改變,刪除原型的一個屬性,繼承它的對象也會刪除
如果b繼承a,c繼承b,那么就會形成原型鏈,如果獲取一個c中沒有的屬性,那么它會從b中找這個屬性,如果b中也沒有,它會從a中找,如果a中還沒有,則返回undefined,此過程稱為委托
關于第二條我有一個疑問,在原型中添加一個屬性,繼承它的對象是否也添加了這個屬性?
如果我直接檢索一個對象的屬性,由于委托的存在而使得我無法確認該屬性是對象還是原型的
例如,我在上面的代碼繼續寫
stooge.lastname = "jack"; var name = another_stooge.lastname; document.writeln(name);
這時,輸出結果是jack,但這個jack是another_stooge的還是stooge的,我并不知道。
這個其實在后面給出了解決方法,就是使用hasOwnProperty()這個方法
stooge.lastname = "jack"; var status = another_stooge.hasOwnProperty("lastname"); document.writeln(status);
運行結果:false
這個方法會檢查對象是否擁有獨有屬性,而且不會檢查原型鏈,如果是,返回true,否則返回false
使用typeof可以檢查對象屬性的類型,用來過濾掉函數,而hasOwnProperty則可以過濾掉不關心的值,那么結合forin語句就可以遍歷對象所有的值了
var name; for (name in another_stooge) { if (typeof another_stooge.name !== "function") { document.writeln(name + ":" another_stooge.name); } }三、函數(Functions)
函數這部分涉及的內容較多,各種調用,回調,級聯,記憶等之前從沒見過的用法
函數對象(Function Objects)對象字面量創建對象,它連接到object.prototype
函數字面量創建函數對象,它連接到Function.prototype
有趣的是,函數在創建完之后,會天生自帶屬性和方法,函數不僅可以當“函數”使用,也能當“對象”使用,函數可以保存到變量,對象,數組中。函數可以當成另一個函數的參數,函數可以返回函數,函數甚至可以擁有函數(注意,不是在一個函數中調用另一個函數,而是函數可以作為另一個函數的屬性),當一個函數是另一個對象的屬性時,函數被稱為方法
四種函數的調用模式 1.方法調用模式這種調用方法在面向對象編程語言中最為常見,當一個函數保存為一個對象的屬性時,可以通過object.function()進行調用
另外,方法可以通過this指針找到自己的對象,在方法內,可以通過this.another_function(),this.property使用或修改對象其他的方法和屬性,在使用thinkphp過程中,this的使用非常高頻,所以這樣的用法并不陌生
2.函數調用模式當函數定義在對象外部時,,通過function(value1,value2,etc)調用成為函數調用模式
函數調用模式有一個麻煩的地方。
當函數定義在對象內部時,this指調用函數的對象,當函數沒有綁定在對象內時,默認指向全局對象(window)
但是當我在函數內定義了一個方法時,this應該指向對象,而實際卻指向全局對象,這使得在定義函數內部的方法時不能使用該對象的其他屬性輔助完成,例如以下
var ob = { value : 1, add : function () { var show = function () { return this; }; return show(); } }; var result = add(); document.writeln(result);
運行結果:[object Window]
由結果可知,show方法中的this并沒有指向ob,而是指向了全局對象。
解決方法:在外部函數內定義一個變量that并賦值為this,內部函數使用that,即可訪問該對象
var ob = { value : 1, add : function () { var that = this; var show = function () { return that.value; }; return show(); } }; var result = ob.add(); document.writeln(result);
運行結果:1
此時,show就可以訪問ob.value了
先上實例
var Person = function(name){ this.name = name; }; var student = new Person("li");//構造一個Person對象,并將name屬性賦值為li document.writeln(student.name);
很眼熟,像極了類的構造函數,用法也是,直接new Function(value,etc)
這種構造對象的模式對于習慣了基于類的語言的我簡直是福音,我看到時滿滿的親切感
書上對于構造器調用不是十分推薦,因為當使用此類函數時不加new修飾符會帶來意想不到的錯誤,既沒有編譯器提醒也沒有運行警告。在后面他提出了一個更好的解決辦法——偽類,會這在之后進行具體的學習
4.Apply,Call調用模式(上下文調用模式)書中對這種調用的介紹很少,我結合書和菜鳥教程做了一些自己的總結
Apply和Call都是函數自帶的方法,功能一樣,用法不同
apply:
函數模式
var array = [1,2]; var add = function(number1,number2){ return number1 + number2; }; var result = add.apply(null,array);//以window作為上下文 document.writeln(result);
2.方法模式
var array = [1,2]; var add = function(number1,number2){ return number1 + number2; }; var o = { name : "jack"}; var result = add.apply(o,array);//以o作為上下文 document.writeln(result);
兩種調用,只是在參數上有所不同,第一個參數為null時,以window作為上下文,如果是對象,則以該對象為上下文
這個上下文是什么?有什么用?
這使我非常困惑,這種調用看似很沒用??!
直到我看到一則實例,我才感受到它的魅力
題目:獲得 div 與 p 標簽, 并添加邊框 border: 1px solid red
一般做法:
var p_list = document.getElementsByTagName("p");//獲取所有p標簽,存到p_list var div_list = document.getElementsByTagName("div");//獲取所有div標簽,存到div_list var i = 0; for( ; i < p_list.length; i++ ) { p_list[ i ].style.border = "1px solid red";//通過for循環,挨個添加樣式 } for( i = 0; i < div_list.length; i++ ) { div_list[ i ].style.border = "1px solid red";//通過for循環,挨個添加樣式 }
使用上下文模式:
var t = document.getElementsByTagName, arr = [];// 偽數組沒有 push 方法,所以這里要 聲明一個 數組 arr.push.apply( arr, t.apply( document, [ "p" ] ) );// 其實是把p標簽,一個個當成參數放了進來 arr.push.apply( arr, t.apply( document, [ "div"] ) );//同上 arr.forEach( function( val, index, arr ) { val.style.border = "1px solid red";//使用foreach,只進行一次遍歷,即可添加樣式 });
上述實例的核心就是將兩個數組合并在一起,進行一次遍歷
對于call,只是參數不再以數組形式封裝,而是function.call(null,value1,value2,etc)這樣的形式,在此不多做贅述
小結通過js,我首次接觸到基于原型繼承設計的語言,剛開始學習對于這樣的設計不是很明白,也不明白原型設計的好處是什么。但是js的廣泛使用證明它必然有它的優勢,我無法理解說明我的技術還達不到去理解一個語言精髓的水平
js中處處體現著萬物姐皆對象,處處是對象,這讓我在一開始感到費解,但隨著進一步的學習,我發現,在js中,對象與其說是對象,不如說是屬性和方法的集合,一個對象在定義之初,系統就已經“免費”贈送了這個集合一些屬性和方法,以這樣的思路去思考,就不難理解為什么函數會是對象了
函數的四種調用方法,方法模式和函數模式我都非常熟悉,只是函數調用模式需要注意this與that,構造器模式作者并不推薦,只是作為了解,而上下文模式設計的巧妙我還不能完全領會,基本處于一頭霧水。
javascript語言精粹這本書感覺很多地方過于簡略,需要我結合網上的一些資料輔助才能看懂,換言之,它并不適合新手入門,然而即便如此,我也抱著能看懂多少算多少的心態,去一窺這個語言的魅力
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/97256.html
摘要:對之前看高級程序設計時沒有注意到的一些知識點,結合本書做以補充語法注釋源于的型既可以出現在字符串字面量中,也可能出現在正則表達式字面量中,如故一般建議使用型注釋保留字語句變量參數屬性名運算符和標記等標識符不允許使用保留字,此外在對象字面量中 對之前看《JavaScript高級程序設計》時沒有注意到的一些知識點,結合本書做以補充 語法 注釋 源于PL/I的/* */型既可以出現在字符串字...
摘要:但采用構造器調用模式,即是使用了前綴去調用一個函數時,函數執行的方式會改變。對象包含構造器需要構造一個新的實例的所有信息。構造器的變量和內部函數變成了該實例的私有成員。 JavaScript 是一門弱類型語言,從不需要類型轉換。對象繼承關系變得無關緊要。對于一個對象來說重要的時它能夠做什么,而不是它從哪里來。 閱讀《javascript語言精粹》筆記! 偽類 js的原型存...
摘要:對象適用于匯集和管理數據。一個對象字面量就是包圍在一對花括號的多個名值對。嘗試從對象里取值將會導致異常。亦不會觸及原型鏈中的任何對象。嚴格模式下,不能用刪除顯式聲明的標識符,名稱或具名函數。 Javascirpt里的對象是無類型的。它對新屬性的名字和屬性的值沒有任何的限制。對象適用于匯集和管理數據。對象可以包括其他對象,所以它們可以容易地表示成樹狀或者圖形結構。 對象字面量 ...
摘要:在中數組是經常被使用到的,我們除了要學習數組的方法,還需要了解誒一下某一些方法是如何來實現的。然而我看了語言精粹中方法的一章,想記錄下書上的代碼,以便加深印象。方法移除數組中的第一個元素并且放回該元素。 在js中數組是經常被使用到的,我們除了要學習數組的方法,還需要了解誒一下某一些方法是如何來實現的。然而我看了《javascript語言精粹》中方法的一章,想記錄下書上的代碼,以便加深印...
摘要:語言精粹讀書筆記第四章函數函數字面量函數字面量包含個部分第一部分,保留字第二部分,函數名,它可以被忽略。這個超級延遲綁定使得函數對高度復用。構造器調用模式一個函數,如果創建的目的就是希望結合的前綴來調用,那它就被稱為構造器構造。 《JavaScript 語言精粹》 讀書筆記 第四章 函數 Functions 函數字面量 函數字面量包含4個部分: 第一部分, 保留字 function...
閱讀 3146·2021-10-12 10:11
閱讀 1851·2021-08-16 10:59
閱讀 2862·2019-08-30 15:55
閱讀 1236·2019-08-30 14:19
閱讀 2046·2019-08-29 17:03
閱讀 2481·2019-08-29 16:28
閱讀 3229·2019-08-26 13:47
閱讀 2897·2019-08-26 13:36