花了一个星期看完了这本书,把随笔写一写,还摘录了一些书里封装好的函数,偶尔多看看(只捡了感受重要的东西)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]];
}
}