花了一個星期看完了這本書,把隨筆寫一寫,還摘錄了一些書裏封裝好的函數,偶爾多看看(只撿了感受重要的東西)javascript
HTML(Model)+CSS(View)+javascript(Controller)
怪異模式是由於DTD觸發,也就是 Document Type Definition (文檔定義類型) <!DOCTYPE html>
多種組織CSS方式 例如能夠按功能劃分 font.css color.css layout.css
此書推薦base.css(通用層)+common(網站級)+css+page(頁面級).css 將網站內的全部樣式,按照職能劃分爲三大類:base common page
若是頁面裏的功能需求很簡單,頁面裏能夠沒有base層代碼,能夠沒有common層代碼,但必定會有page層代碼。base層和common層都是屬於框架級的,page層是屬於應用級的,它能夠調用base層得接口和common層的組件。
base和common就是接口接口接口,底層接口
base就像是把一條路捋平了,common就是把路鋪上瀝青,page就是一輛小車車,而後就讓它飛奔起來~~~
HTML規範:
DTD統一用<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/><html/DTD/><html1-transitional.dtd">
HTML應當在保證彈性的基礎上儘可能減小嵌套層數。
嚴格區分做爲內容的圖片和做爲背景的圖片。做爲背景的圖片採用CSSsprite技術,放在一張大圖裏。大圖的安排也聽從common+app的方式,全站採用的圖片應告知公用組件維護者,添入common.gif中,各欄目的圖片,應放入app.gif中。CSS sprite技術的優勢是減小了http請求數,但使圖片面向CSS的background-position增長了耦合度,也增長了維護成本。若是圖片有修改,不要刪除已添加的圖片,在空白處新增修改後的圖片,減小修改風險。
CSS規範:
CSS Reset用YUI的CSS Reset
CSS採用CSSReset+common .css+app.css
爲避免組件的上下外邊距重合問題和IE的haslayout引起的Bug,各模塊除特殊需求,一概採用marginTop設置上下外邊距,以下栗子:
<p>000000000</p>
<p class="marginTop10 marginBottom10">00000000</p>
<p>000000</p>
錯誤
<p>000000000</p>
<p class="marginTop10">00000000</p>
<p class="marginTop10">000000</p>
正確
CSS用一行的寫法,避免函數太長,不利於查找
--------------------------JS----------------------
(function(){})():
用匿名函數將腳本包起來,能夠有效控制全局變量,避免衝突隱患;
window.onload事件:window對象會在網頁內元素所有加載完畢以後觸發onload事件
可是會存在一個問題,window的onload事件要求網頁內全部的元素所有加載完畢後纔會觸發。
可使用JS框架提供的DOMReady事件代替window.onload,做用很像,可是DOMReady只判斷頁面內全部的DOM節點是否已經所有生成,而後就觸發加載。
CSS放在頁頭,JavaScript放在頁尾
還有若是非要放在頁頭
那麼CSS文件必定要再JS文件前面,JS容易阻塞網頁
JS的分層也跟CSS的分層差很少
從下往上依次是base層,common層,page層
base層得JavaScript和頁面裏的具體應用邏輯無關,是屬於框架級的,它提供的接口須要供全局做用域調用。
儘可能使用命名空間來減小全局做用域變量的個數
原生讀取cookie時一件很是痛苦的事!cookie沒法直接讀取某個鍵中保存的值,只能從ducument.cookie中將全部的鍵值對所有讀出來,再使用split,indexOf,slice等方法操做字符串截取本身須要的鍵的值!
爲了方便分辨class是用於css的掛鉤仍是JavaScript的掛鉤,咱們能夠給用於JavaScript的class加上「J_」做爲前綴;
DRY規則----don't repeat yourself(程序中不要將相同的代碼重複編寫屢次)
在對函數傳參時,有普通傳參這種方式,可是可使用hash對象傳參的方式,這樣能夠避免不用把不須要的參數傳進去,還非得設置null這樣的數值;
下面舉個栗子:
//普通方式傳參
function test(a,b,c){
var oA=a||1,oB=b||2,oC=c||3;
}
test(4,5,6) ;
test(null,7,8);
test(null,null,9);
//用hash對象傳參
function test2(config)
{
var oA=config.a||1,oB=config.b||2,oC=config.c||3;
}
test({a:4,b:5,c:6});
test2({b:7,c:8});
test2({c:9});
使用hash對象傳參,能夠提升函數調用的靈活性,提升函數擴展性。
面向過程的思惟方式是典型的計算機思惟方式---輸入數據給處理器,處理器內部執行運算,處理器返回結果。
面向過程的方式編程
var name="adang";
var state="awake";
var say=function(oName){
alert("I'm"+oName);
}
var sleep=function(oState){
oState="asleep";
}
say(name);
sleep(state);
面向對象方式編程
var adang={
name:"adang",
state:"awake",
say:function(){
alert("I'm"+this.name);
},
sleep:function(){
this.state="asleep";
}
};
adang.say();
adang.sleep();
屬性本質實際上是個變量,也就是面向過程當中的數據,而行爲的本質實際上是函數,也就是面向過程的處理函數。不一樣的是,面向過程當中,數據和處理函數並無關聯起來,共同屬於某個物件。而面向對象將數據和處理函數定義到了一個對象的內部,做爲這個對象的屬性和行爲存在。在對象外部,屬性和行爲能夠用對象的屬性和對象的行爲來調用,從而讓程序有了按真實世界的思惟方式進行描述的能力。在對象內部,對象的屬性和行爲經過this關鍵字關聯起來。
面向過程編程全部的數據和處理函數都是公有的,整個編程的思惟過程就是定義數據,定義處理函數,而後將數據傳給處理函數進行處理,處理函數之間也能夠互相調用,數據和處理函數緊密耦合。
面向對象編程的思惟過程是定義一個個對象,對象有本身的屬性和行爲,由於屬性和行爲都是從屬對象,因而有了「對象內」和」對象外「的概念,整個程序能夠油一堆對象組成,對象與對象之間可能會有通訊,爲了實現這種通訊,對象會將本身的部分屬性和行爲設計成公有,暴露出來成爲通訊的接口。對象和對象之間的通訊都是創建在接口的基礎上的。固然咱們能夠將對象全部的屬性和行爲都設爲公有的,所有都做爲接口,但接口越多,會讓對象之間耦合越緊密,增長維護難度,因此通常狀況下,咱們都會盡可能將對象的屬性和方法設爲私有,只講必要的行爲設爲公有。
面向對象英文全稱Object Oriented ,簡稱OO。OO其實包括OOA(Object Oriented Analysis ,面向對象分析),OOD (Object Oriented Design,面向對象設計)和OOP(Object Oriented Programming,面向對象的程序設計)。
一個典型的OO編程過程應該是先整理需求,根據需求進行OOA,將真實世界的客官物件抽象成哼程序中的類或對象,這個過程常常會用到的是UML語言,也稱UML建模,OOA的輸出結果是一個個類或對象的模型圖。而後就用OOD,這裏通常是爲了處理類之間耦合關係,設計類或對象的接口,此時會用到各類設計模型,例如觀察者模式,責任鏈模式等。OOA和OOD是個反覆迭代的過程,它們自己沒有很是清晰的邊界,是互相影響,制約的。等OOA和OOD結束以後,纔到OOP,進行實際的編碼工做。
OOA和OOD是面向對象編程的思想和具體語言無關,而OOP是面向對象編程的工具,和選用的語言相關。OOP是OOA和OOD的底層,不一樣緣由的語法不一樣,因此OOP不一樣,
但OOA和OOD與具體要求語言無關,通常狀況下能夠輕易跨語言重用。
但實際上呢,一個OOA能力是很是重要的,OOP通常是用不到那麼複雜的設計,OOP只佔了一小部分的時間
「高內聚,低耦合」聚合指的是把一個複雜的事物當作若干個比較簡單的事物的組裝提,從而簡化對復瑣事物的描述,「高內聚」就是指對象(或類)對外提供的接口很是簡單易懂,複雜的底層操做都封裝在對象(或類)的接口內部,對用戶透明。耦合指的是類與類之間關聯和依賴的程度,低耦合就是指類與類之間依賴的程度低,類與類通訊須要關聯的接口越少,耦合程度越低。
決定聚合和耦合程度的是OOA和OOD,OOA和OOD是工做在架構層面的,而OOP是工做在編碼層面的。
從大局上決定程序品質的,不是OOP,而是OOA和OOD,這是不少工程師要注意的。
原來JavaScript也有類
//函數做爲普通函數
function sayHi(){
alert("hi");
}
sayHi();
//函數做爲類
function Animal(name){
this.name=name;
this.type="animal";
this.say=function(){
alert("I'm a(an) "+this.type+",my name is "+this.name);
}
}
var myDog=new Animal("wangcai");
myDog.say();
這樣的實例方法,而後實例後就是Animal類;
實例化類時JavaScript和C#這種正統面嚮對象語言並無明顯差異,差異主要在類的定義方式上面。
JavaScript是基於原型的語言
經過new實例化出來的對象,其屬性和行爲來自於兩部分,一部分來自於構造函數,另外一部分來自於原型。什麼事原型呢?當咱們聲明一個類時,其實同時生成一個對應的原型,例如咱們定義Animal這個類時,會生成一個與Animal類對應的原型,經過Animal.prototype能夠指向這個原型,原型能夠經過constructor指向Animal類,更確切地說,是指向Animal類的構造函數。
栗子:
//定義Animal類的構造函數
function Animal(){
....
}
var a=Animal.prototype; //a指向Animal類對應的原型
var b=a.constructor; //b指向a對應的類的構造函數
alert(b==Animal) //true
this關鍵字,可讓屬性和方法在構造函數和原型間通訊。
在JavaScript中公有仍是私有是經過做用域實現的。
this×××定義的屬性是公有的,而用var×××定義的屬性是私有的
將全部的屬性和行爲,不管公有仍是私有所有寫在構造函數雖然方便,可是不推薦這麼作,由於在內存中一個類的原型只有一個,寫在原型中的行爲,能夠被全部實例所共享,實例化的時候,並不會在實例的內存中再複製一份,也就是說全部實例共用那個內存了,而寫在類裏的行爲,實例化的時候回在每一個實例裏複製一份;
把行爲寫在原型裏能夠減小內存消耗,沒有特殊緣由,推薦儘可能把行爲寫在原型裏,寫在原型中的行爲必定是公有的,並且沒法訪問私有屬性,因此如何處理私有行爲和私有屬性是個難題。
在原型中定義私有行爲,但經過給屬性和行爲的名稱前面加上「_」來約定它是私有的,這是一種命名約定,它並不能真正實現行爲的私有,但它可讓工程師知道它是設計成私有的,從而避開像公共行爲那樣調用它
屬性就寫在構造函數中,行爲方法就寫在原型中
避免直接訪問類的屬性,能夠經過get和set方法來獲取和設置屬性
function Animal(name){
var name;
this.getName=function(){
return name;
}
this.setName=function(o){
name=o;
}
}
//而後實例化後就能夠調用getName獲取對應屬性值了,setName就能夠設置屬性值
這麼作會佔用不少內存,可是它能夠更好的保護屬性
只要是類就會有原型,無論它是自定義類仍是JavaScript的內置類,咱們能夠經過修改內置類的原型,讓JavaScript基本類型的對象獲取一些有趣的功能。
不管在類的構造函數中仍是原型中,this都指向實例化的對象。
拓展Array的例子,
修改內置類的原型:Array.prototype.each=function(fun){
for(var i=0,n=this.length;i<n;i++){
fun(this[i],i);
}
}
var a=[1,2,3];
alert(a); //1,2,3
Array.prototype.toString=function(str){
return "I'm an array";
}
alert(a); //I'm an array
值得一提的是,「alert(a)」時,自動調用了a的toString方法。在須要字符串時,對象會隱式地自動調用toString方法,包括咱們自定義的對象。內置類的方法能夠重寫,但屬性卻不能重寫
給自定義類定義toString方法,能夠爲咱們在調試時提供更多有用的信息。
在JavaScript中,包括內置類和自定義類,全部的類的祖先類都是Object,因此若是想對全部對象都拓展方法,能夠經過修改Object類的原型實現
使用JavaScript對HTML標籤屬性操做:
class是JavaScript的保留字,因此在獲取HTML標籤的class屬性時,要改用className。
使用node.×××的方式獲取常規HTML標籤的屬性值,跨瀏覽器兼容性比node.getAttribute("×××")好。
要注意的是,自定義標籤屬性一樣能夠再JavaScript中獲取,可是和常規屬性不一樣,Firefox下沒法經過node.×××獲取到自定義屬性值,只能使用node.getAttribute("×××")獲取,IE下面就能夠哦~!
將複雜類型的數據轉化成字符串,就稱爲數據的序列化,其逆操做就是反序列化。
字符串的反序列化是經過eval函數實現的。只要字符串長得像JavaScript支持的數據格式(json),就能夠進行反序列化,而與是否是Ajax的返回數據無關。
-----------------------------------------------------------------錯誤------------------------------
1.tabContents[i] is undefined(在遍歷數組時對DOM監聽事件,索引值始終等於遍歷結束後的值)
解決方案:
1)利用閉包
2)給DOM節點添加index屬性,屬性值就等於索引,(能夠應用在輪播圖中各個按鈕與圖片的關聯)
2.IE下面JS的this指向問題 "'tabContents[...].style'爲空或不是對象"。(JavaScript僞協議和內聯事件度this的指向不一樣)
1)使用匿名函數能夠解決這個問題哦!
2)使用call和apply調整this指向(只知道這玩意是繼承那的,不知道怎麼調整)
什麼是事件冒泡
在一個對象上觸發某類事件(好比單擊onclick事件),若是此對象定義了此事件的處理程序,那麼此事件就會調用這個處理程序,若是沒有定義此事件處理程序或者事件返回true,那麼這個事件會向這個對象的父級對象傳播,從裏到外,直至它被處理(父級對象全部同類事件都將被激活),或者它到達了對象層次的最頂層,即document對象(有些瀏覽器是window)。
------------摘錄了幾個封裝好的函數--(敲的好辛苦啊)-------------
//透明度問題 利用js代碼解決IE下的透明度問題
function setOpacity(node,level){
node=typeof node==="string"?document.getElementById('node'):node;
if(document.all)
{
node.style.filter='alpha(opacity=' + level + ')';
}else{
node.style.opacity=level/100;
}
}
//阻止事件冒泡
function stopPropagation(e){
e=window.event||e;
if(document.all)
{
e.cancelBubble=true;
}else{
e.stopPropagation();
}
}
//去除字符串首尾的空白字符
function trim(ostr){
return ostr.replace(/^\s+|\s+$/g,"");
}
//類型判斷
function isNumber(s){
return !isNaN(s);
}
function isString (s) {
return typeof s==="string";
}
function isBoolean(s){
return typeof s==="Boolean";
}
function isFunction(s){
return typeof s==="function";
}
function isNull(s){
return s===null;
}
function isUndefined(s){
return typeof s==="undefined";
}
function isEmpty(s){
return /^\s*$/.test(s);
}
function isArray(s){
return s instanceof Array;
}
//第一個參數是class名,第二個參數是父容器,缺省爲body節點,第三個參數爲DOM節點的標籤名。
function getElementSByClassName(str,root,tag){
if(root){
root=typeof root=="string" ?document.getElementById(root):root;
}else{
root=document.body;
}
tag=tag||"*";
var els=root.getElementsByTagName(tag),arr=[];
for(var i=0,n=els.length;i<n;i++){
for (var j=0,k=els[i].className.split(" ");,l=k.length;j< 1; j++){
if(k[j]==str){
arr.push(els[i]);
break;
}
}
}
return arr;
}
//繼承功能
function extend(subClass,superClass){
var F=function(){};
F.prototype=superClass.prototype;
subClass.prototype=new F();
subClass.prototype.constructor=subClass;
subClass.superClass=superClass.prototype;
if(superClass.prototype.constructor==Object.prototype.constructor){
superClass.prototype.constructor=superClass;
}
}
//Cookie的操做
GLOBAL.namespace("Cookie");
GlOBAL.Cookie={
//讀取
read:function(name){
var cookieStr="; "+document.Cookie+"; ";
var index=cookieStr.indexOf("; "+name+"=");
if(index!=-1){
var s=cookieStr.substring(index+name.length+3,cookieStr.length);
return unescape(s.substring(0,s.indexOf("; ")));
}else{
return null;
}
};
//設置
set:function(name,value,expires){
var expDays=expires*24*60*60*1000;
var expDate=new Date();
expDate.setTime(expDate.getTime()+expDays);
var expString=expires ? ";expires ="+expDate.toGMTString() : "";
var pathString=";path=/";
document.Cookie=name + "=" +escape(value) + expString +pathString;
};
// 刪除
del:function(name){
var exp=new Date(new Date().getTime()-1);
var s=this.read(name);
if(s!=null) {
document.cookie=name+"="+s+";expires="+exp.toGMTString()+";path=/"
};
}
};
//封裝起來的命名空間函數,爲了解決衝突命名
var GLOBAL={};
GLOBAL.namespace=function(str){
var arr=str.split("."),o=GLOBAL;
for(i=(arr[0]=="GLOBAL")?1:0;i<arr.length;i++){
o[arr[i]]=o[arr[i]]||{};
o=o[arr[i]];
}
}