标签:
高质量的js
1. 良好的编程习惯
2.Js分层和js库
3.面向对象编程
4.编程实用技巧
?良好的编程习惯
1.切记不要全局变量泛滥(会产生冲突)
方法:用匿名方法将脚本包起来,将变量的作用域控制在匿名函数内(function(){})();
2.匿名函数变量的通信
方法:我们使用一个{}对象类型的变量作为全局变量,需要多个全局变量做通信桥梁的,可以将这些变量作为全局对象的属性,这样保证了全局变量的个数足够少,同时扩展性非常好,一般用 GLOBAL
缺点:如果命名比较简单,还是很容易覆盖的
解决方法:采用命名空间
JavaScript 的命名空间(最新版本的JavaScript还是不支持命名空间,
在JavaScript中,类机制使用了原型(prototype)模式。)
并不是真正的命名空间, 只是在脚本内部创建一个封闭的小空间, 必须通过特定的空间名称才能对空间内部的代码进行访问, 这样可以防止同名函数和变量发生冲突, 也可以更方便地管理代码, 就像 .NET 的命名空间 (namespace) 和 Java 的包 (package) 一样.
(function{
function $(id)
{ return document.getElementById(id); }
// 显示对应 ID 的对象的节点类型名字
function myMethod(id) { alert($(id).nodeName);
}
// 这是对外的接口
window[‘myNamespace‘]= {} window[‘myNameSpace‘][‘$‘] = $; })();
?生成命名空间的函数
Var GLOBAL={}(没看懂)
GLOBAL.namespace=function(str)
{
Var arr=str.split(“.”),
o=GLOBA;
for(i=(i=arr[0]==”GLOBAL”)?1:0;i<arr.length;i++)
{
o[arr[i]]=o[arr[i]]||{};
o=o[arr[i]];
}
}
注意添加注释,很重要
Js是脚本语言,浏览器下载到哪就执行到哪
关于js css在文档中的顺序
因为浏览器是从上到下加载的
则顺序最好是css html js---------然后就是压缩(所谓压缩是指指去掉空格和换行,去掉注释,将复杂变量名替换为简单的变量名)
?js分层与js库
一般分为base common和page
Base层:()
作用:1.完成浏览器兼容问题 2.扩展js底层提供的接口
为common和page提供接口
Common层
作用:依赖base层提供的接口,为page层提供组件
Page层
作用:依赖前两层,完成页面内的功能需求
获得 body 元素的节点类型:
document.body.nodeType; //1
如果节点是元素节点,则 nodeType 属性将返回 1。
如果节点是属性节点,则 nodeType 属性将返回 2。
代表元素或属性中的文本内容。返回3
Base层第二个提供接口
Trim()
Function trim(oStr)
{ return oStr.replace(/^\s+|\s+$/g, “”);
}
Function isNumber(s)
{
Return !isNaN(s)
}
Function isString(s)
{ return typeof s==”string”
}
Function isArray(s)
{
Return instanceof Array;
}
Function getByClass(oParent,sClass)
{
var aResult=[];
Var childNodes=oParent.getElementsByTagName(“*”);
Var re=new RegExp(“\\b”+sClass+”\\b”,”i”);
For(var i=0;i<childNodes.length;i++)
{
If(re.test(childNodes[i].className))
{
aResult.push(childNodes[i]);
}
}
Return aResult;
}
补 网站重构的原因:
1.根据W3c标准进行重构后,可以让前端代码组织更有序,显著改善网站的性能,对搜索引擎也友好
2.重构后的网站带来更好的用户体验,用XHTML+CSS的布局,文件更小,下载速度更快
?编程实用技巧
1.弹性
Tab制作
var tabMenus=document.getElementById("tab_menuWrapper").getElementsByTagName("li");
var tabcontent=document.getElementById("tab_contentWrapper").getElementsByTagName("div");
for( var i=0;i<tabMenus.length;i++)
{
tabMenus[i].index=i;
tabMenus[i].onclick=function()
{
for(var j=0;j<tabMenus.length;j++)
{
tabcontent[j].style.display="none";
}
tabcontent[this.index].style.display="block";
}
}
在遍历数组时对DOM元素的监听事件的索引值始终等于遍历后的值
不懂(问题)
还有一个办法是利用闭包
函数声明和函数表达式不同之处在于,
一、Javascript引擎在解析javascript代码时会‘函数声明提升’(Function declaration Hoisting)当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式,
二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用 。以下是两者差别的两个例子。
fnName();
function fnName(){
...
}//正常,因为‘提升’了函数声明,函数调用可在函数声明之前
fnName();
var fnName=function(){
...
}//报错,变量fnName还未保存对函数的引用,函数调用必须在函数表达式之后
var fnName=function(){
alert(‘Hello World‘);
}();//函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
function fnName(){
alert(‘Hello World‘);
}();//不会报错,但是javascript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
要在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。
Id和标签名都是取得元素的最佳选择,最好用class
2,可复用性
组件需要指定一个根节点,以保证每个组件之间的独立性
3.避免产生副作用(即在DOM元素有多个类时删除一个,或者添加一个)
Function addClass(node,str)
{ var re=new RegExp(“\\b”+str+”\\b”);
If(!re.test(node.className))
{ node.className=node.className+” ”+str;
}
}
Function removeClass(node,str)
{
var re=new RegExp(“\\b”+str+”\\b”);
Str.replace(re,””);
Node.className=str;
}
4.this详解
1.settimeout/setintetval中的this指向window
2.函数中的this是指新建的对象
3.DomNode.XXX中this指向dom节点
5 hash传参数(即参数是json)
?面向对象编程
面向过程编程:将数据和处理函数分为两部分,程序以处理函数为核心
面向过程的思维是描述一个个动作,而面向对象是描述一个个物件(即对象)对象是由属性和行为组成对应可观世界的状态和动作
属性的本质是变量,行为的本质是函数
面向对象(OO)包裹面向对象分析(OOA),面向对象设计(OOD),面向对象编程(OOP)
优秀的程序是高内聚(类对外提供的接口很简单易懂,用户知道的底层的细节越少,聚合度越高),低耦合(类和类之间的关联和依赖程度)
Js语言分析
Js是基于原型的,属性和和行为来自两部分,一部分来自构造函数,另一部分来自原型(我们声明一个类,同时生成一个对应的原型 class.protoType)class.protoType.constructor=class(实际是构造函数)
构造函数中的属性和行为的优先级要高于原型中定义的属性和行为
关于变量的私有和公有,js是通过作用域实现的
Function animal(name)
{ this.name=name;//此处是公有属性
Var a=20;//私有属性
var move=function()
{}
}
写在原型中的行为一定是公有的,而且无法访问私有属性,把行为写在原型中可以减少内存(因为是引用)写在构造函数中实例化的时候是复制一份
Function animal(name)
{ //set和get的使用
This.setname=function(o)
{ name=o;
}
This.getname=function()
{ return name;
}
}
Js中的传值与传址
Var a=10;
Var b=a;//此处是将a的值复制一份给b
Var c=[1,2,3];
Var d=c; //此处是传址,将变量c指向的数据的内存地址传给变量d
对复杂的数据类型(数组和hash)进行赋值控制,需要做的是
Var a=[1,2,3];
Var b={name:”aDam”,sex:”famle”};
Var c=[],d=[];
For(var p in a)
{
c[p]=a[p];
}
b同
对于数组另一种赋值的方法是
c=a.slice();或者 a.concat();
Prototype实质上也是hash对象,对于它除了使用for循环以外,还可以是 subClass=new oParent();
对于内置类:date array 等,我们可以扩展内置类的方法,也可以重写内置类的方法
Var a=[1,2,3];
Alert(a); //得到的是 1,2,3
在alert(a)时,自动调用了a的tostring方法,在需要字符串时,对象隐式调用tostring
内置类的方法可以重写,但是属性确不能重写
例如数组中的length不能更改
在js中包括内置类和自定义类,所有类的祖先都是object,如果对所有的对象都扩展方法,通过修改object的原型即可
Object.prototype.test=function()
{
Alert(“ok”)
}
则下面的对象如论是数组,字符串等,都可以用,但是这种修改内置类的方法不适合多人合作
另一种方法是 新建一个内置类,将内置类的实例作为参数传递给构造函数,在自定义类里扩展方法,这种做法的思想是将内置类在封装一层,以此保护内置类的原型不被污染。
标签的自定义属性
定义在html标签中的属性,在js里也可获得,获取方式两种:
1.node.getAttribute()方法
2.Node.shuxing
其中第二种比第一种的跨浏览器兼容性更好
关于html中自定义的属性,在js中获取的时候IE下使用node.***=;FF下用node.getAttribute();
总结:对于常规属性,统一使用node.xxx的方式读取,对于自定义属性,统一使用node.getAttribute
将复杂的数据类型转化为字符串,称为数据的序列化,其逆操作是数据的反序列化
其中反序列化用的最多的是ajax
字符串的反序列化是通过eval实现的,字符串长的像数组或者json就会转化为相应的格式
例如 info=(“(”+info+”)”);
Function handler()
{
Alert(“123”);
}
If(document.all)
{
node.attachEvent(“onclick”,handler);
}
Esle
{
node.addEventListener(“click”,handler,false);
}
改变DOM节点的三种方式
1.使用style
2.设置类
3.用js新建一个css
Function addStyleNode(str)
{
Vat styleNode=document.createElement(“style”);
styleNode.type=”text/css”;
If(styleNode.styleSheet)
{
styleNode.styleSheet.cssText=str;//此处的str可以是css语句
}
Esle
{
StyleNode.innerHTML=str;
}
}
标签:
原文地址:http://www.cnblogs.com/wenyan/p/4881439.html