这一节是继上一节高质量的Javascript

7)编程实用技巧

1:弹性

从 一个标签区和内容区的实例(就是点击不同的标签菜单显示不同的内容块)来说明不需要每个tabmenu都设置onclick事件,为了让程序更有弹性,可 以将所有的点击时间封装成一个函数,变化的标签作为参数传入实现点击不同的标签显示对应的内容块,这样标签的数量可自适应,可增可减,而js代码可以不用 变动,只需要修改html的标签就可以。-------------这点我想做过项目的伙伴们都能深深的体会到。

琐碎知识点:

js 一个非常经典的问题:在遍历数组时对DOM监听事件(如上例中的菜单单击事件tabMenus[i].onclick),索引值始终等于遍历结束后的值。 解决这一问题可以用闭包,或者给每个DOM节点添加Index属性用来标示区别。---------我遍历一般用jquery的each函数,挺好用的, 没用过Dom,但是还是一个值得注意的地方。

2:可复用性

因为一个html页面的id只能出现一次,所以,如果你的程序需要被多次复用,就一定不能用id来标识,不能用id作为js获得DOM节点的挂钩,更好的应该是使用class.  在做项目过程中,我们可以通过class取得一组Dom标签,但由于id的唯一性,只适合取某个固定的标签。

组件需要指定根节点,以保持每个组件之间的独立性。--------具体的可能要看书上的代码示例来体会。(就是尽管有相同的class来标识同类结构(一个组件),但是不同的组件与组件之间还需要指定一个父节点来区别对待)。

3:通过参数实现定制

如果每个tab标签需要不同的样式,这个时候就只能根据每个tabMenu的唯一标示作为参数传到处理函数,在函数中根据不同的标识来选择不同的样式

如果一个函数内某个因素很不稳定,我们可以将它从函数内部分离出来,以参数的形式传入,从而将不稳定的因素和函数解耦。---与第一点弹性有相似处

4:this关键字的指向

在js全局域中  this指向window.

A:JavaScript伪协议和内联事件对于this的指向不同:

  伪协议:a标签的href="javascript:alert(this==window)"     结果:弹出true       伪协议中this指向window

  内联事件:onclick="alert(this.tagName)"                          结果:弹出a          内联事件的this指向当前的Dom元素 

B:setTimeout和setInterval也会改变this的指向,在这两个函数中  this指向window

C:DomNode.on***事件也会改变this的指向,this会指向当前调用时间的Dom结点。

使用匿名函数可将B,C中this的指向改变。

例:

 1 <script type="text/javascript">
2 var name = "global-name";
3 var btn = document.getElementById("btn");
4 var test = {
5 name: "test-name",
6 say: function () {
7 alert(this.name);
8 }
9 }
10 test.say(); //输出test-name
11 setTimeout(function () { test.say() }, 1000); //输出test-name 匿名函数会改变指向,谁调用就指向谁
12 /*
13 setTimeout和setInterval两个函数的调用方式,第一个参数应该是函数指针,或字符串
14 */
15 setTimeout('test.say()', 1000);         //作为字符串,还是由test调用,输出test-name
16 setTimeout(test.say, 1000);         //作为函数指针,输出global-name setTimeout的直接调用指向方式,this指向window
17
18 setInterval(function () { test.say() }, 1000); //输出test-name
19 setInterval('test.say()', 1000); //输出test-name ,由test主调
20 setInterval(test.say, 1000); //输出global-name
21 setTimeout(function () { alert(this == window) }, 1000); //输出true, this为全局window对象
22
23 $(function () {
24 var btn2 = document.getElementById("btn");
25 btn2.onclick = function () { test.say() }; //输出test-name
26 btn2.onclick = function () { alert(this == btn2) }; //输出true, this为DOM元素对象
27 });
28 </script>
29 <input type="button" name="btn-name" id="btn" value="test-btn" />

总结:1:如果setTimeout和setInterval调用的处理函数,该处理函数是“直接调用的函数”,那么this指向window

   2:DomNode.on***关联的处理函数,该处理函数是“直接调用的函数”,this指向Dom结点

   3:如果将上面的处理函数用匿名函数封装起来,那么,处理函数的调用方式:由直接调用变为间接调用;这样就不会受到外面调用函数的影响,this该指向谁就指向谁

自己的话:一般来说,this----该动作是谁调用的,那么this就指向调用者,只有碰到setTimeout、setInterval、btn.on***等会改变指向的函数,才不会遵守基本规则,但是也可以通过匿名函数的间接调用来解决,这样又变回了一般状态。


另外还可以通过call和apply函数来改变处理函数的this指向,test.say.call(btn); test.say.apply(btn);  this 直接指定的。

5:预留回调接口

我所理解的就是,在函数中预留出一个参数handler,该参数的实参是一个函数。 判断回调函数是否有用,if(handler){ handler(参数);//调用回调函数;}

添加回调的接口可以参加代码的可扩展性。

6:编程中的DRY规则

DRY----don't repeat yourself,强调在程序中不要将相同的代码重复编写多次,更好的做法是只写一次,然后多次引用。提高重用率,减少代码量

7:用hash传参

比较: 普通传参方式:参数量大,而且参数的顺序很重要,

    hash传参方式:hash是一个key-value的集合,可包含任意类型的数据,用hash对象传参,可以提高函数调用的灵活性,没有顺序的控制

如: test函数有6个参数,调用时有些为空,有些不为空,普通传参: test(null,null,null,null,null,"hello"); 用hash传参: test( {str:"hello"} ) 显然第二种简单直观.

8)面向对象编程

1:面向对象

将数据和处理函数定义到了一个对象的内部,作为这个对象的属性和行为存在,在对象的内部,属性和行为通过this关键字来访问,在对象的外部,用对象的属性和对象的行为来调用。   额~,抽象的概念,理解起来就是别扭。

它的思维过程是定义一个对象,对象有自己的属性和行为。属性和行为都从属于对象,于是有对象内,和对象外的概念。

整个程序可以由一堆对象组成,对象和对象之间可能会有通讯,为了能相互访问,于是就有了私有和公有的概念。

2:js的面向对象

A:类的概念 

 一般的类定义,都要class关键字,js中的类没有class关键字,它是用函数来充当类的函数在js中既可以用作普通函数,也可以当类来使用,当充当类时,又担负着构造函数的作用。

fuction test(){//code...}

  调用方式: 函数充当普通函数,直接使用()进行调用。 如:test()

        函数充当类时,使用new来实例化。如:var c=new test();

B:原型(prototype)

原型在js中是一个很重要的概念,因为JS是基于原型的语言,通过new实例化出来的对象,其属性和行为来自于两部分:1:构造函数(既函数本身),2:原型

原型的概念及由来:我们只需要知道“在声明一个类的时候,同时就生成了一个对应的类的原型。”------------我理解为同样的生命周期。

通过test.prototype就可以指向这个原型, 而原型也可以通过它的constructor属性指向test类,具体指的是test类的构造函数。

只有当函数作为类使用,new出来一个对象时,原型才具有它存在的价值(个人观点)

原型是个hash对象,也可以分开定义

如:test.prototype={                    分开定义:

  name:"***",                       test.prototype.name="***";

  type:"***",                         test.prototype.type="***";

  say:function(){.....}                   test.prototype.say=function(){...};

}

C :优先级

当构造函数和原型中都定义了同名的属性和行为,则构造函数中的属性和行为优先级要高,它会覆盖原型中的属性和行为。

this关键字无论是出现在构造函数还是原型中它指代的都是实例对象。能改变this指向的函数就另当别论。

D:公有和私有

js中没有public,protect,private等关键字,js中的公有还是私有是通过作用域来实现的。

用this.***定义的属性都是公有的(原因:在构造和原型中的this 都是同一个实例对象,在原型中可以访问得到),而用var ***定义的属性都是私有的(在原型中访问不到)。方法的公有私有也一样用this区别开来。

习惯: 定义类时,一般我们会把属性(变量)放在构造函数里------方便构造函数接收参数,而行为(方法)放在原型里。

原因:因为在内存中一个类的原型只有一个,写在原型中的行为可以被所有实例共享,实例化时不会在实例的内存中复制一份;而写在类中的行为,会每个实例都会复制一份。--------------为了减少内存消耗。

自己的话:实例化时,原型中的属性和行为是引用,构造函数中的属性和行为是复制。

3:继承

琐碎知识点:在js中,fuction作为普通函数存在时,直接使用()进行调用,函数内的this是指向window;

          function作为类存在时,通过new实例化,类里面的this指向实例对象。

A:构造函数中属性和行为的继承

为了实现构造函数中属性和行为的继承,可以通过call/apply方法来实现。

如:

当实例化B的对象时就能访问到构造函数里的属性和方法。

B:原型中属性和行为的继承

琐碎知识点:js中的传值和传址。

在js中,赋值语句会用传值和传址两种不同的方式进行复制,如果是数值型,布尔型,字符型等基本数据类型,将复制一份数据进行赋值。---传值

如果是"数值,hash对象等复杂类型"(数值,hash对象可包含简单类型数据),在进行赋值时会直接使用内存地址赋值。-----传址

原型中的属性和行为的继承,我们可以直接将A的原型赋值给B的原型,如B.prototype=A.prototype

这样B的实例及B.prototype 是可以访问A类原型中的say方法,但是prototype本质上是一个hash对象,它的赋值是传址的方式,当我们在B的原型中在添加一个AddFunctionForB()方法时,由于传址方式,在A的原型中也会添加B的AddFunctionForB()方法.

如:

为了解决这个问题,我们用另一种方法实现prototype的传值-new somefunction() ----new出基类的对象,然后重新定向B类的构造。

在上面的代码中我们定义了A类及A类的原型、B类;我们只需要将B类的原型中指向A类的实例对象(这时,B类会继承A类的构造及原型中的属性和方法),这样就可以访问A类原型中的方法。但由于这种赋值会使得B.prototype.constructor指向了A类的构造,所以我们要将它纠正,重新指向B类。

这样就解决了上面的问题,既能从原型继承方法,又不会引起不必要的混乱。

9)prototype和内置类

从第8点知道了prototype和类的关系,现在看看prototype和js自带的内置类的关系。

Js的内置类包括Array,String,Function等 如Array提供length属性,push.pop方法,String提供length属性,replace.split方法 ,Fuction提供Call.apply方法.

一般内置类我们一般不用New实例化,习惯更简单的方式,如 var a="sssss";  而不是 var a=new String("sssss");

只要是类就会有原型,So 我们可以对内置类的原型进行修改,以重写或扩展它的功能。

如:常见的有 Array.prototype.each=function(){....}        Array.prototype.map=function(){.....}

里面可能会涉及到this指针的指向,我们只需要记住,在类的构造函数和原型中的this ,都是指向该类实例化的对象。

注意:内置类的方法可以重写,比如toString()方法,但是 他的属性不能重写,如length;

 

10)标签的自定义属性

在html语言中的标签一般有自己的属性,如 id,class href等,我们有时候会用到自定义的属性
为了从兼容性来考虑,用JS来读取属性时,笔者建议对于常规属性,统一使用node.***的方式读取,对于自定义属性,统一使用node.getAttribute("***")读取。

自定义属性一个非常有用的技巧:----将普通字符串转换为hash对象或数组

字符串的反序列化-----------通过eval函数来实现。

如在a标签里自定义一个属性<a id="a" userinfo="name:'alice' , age:22 , pwd:'123456' " ></a>

取到a的userinfo属性值 var info = document.getElementbyId("a").getAttribute("userinfo");

            alert(typeof info) //string 类型      访问info.name  info.age都访问不到

            info=eval("("+info+")"); 转化为对象类型; 访问info.name  输出alice ;  访问 info.age   输出22;

11) 标签的内联事件和event对象

在IE下,event是window对象的一个属性,是全局作用域下的; 在FF中,event对象是作为事件的参数存在。

在标签的内联事件中,FF下,使用arguments[0]可以访问到event对象。不是内联事件,可以给处理函数传参来访问  funtion(e){...}

关于event对象前面的章节中也有讲过,这里就不再描述了。

12)一些规则

基本在前面的内容中均已描述过,包括css命名规则、注释规则、html规范、css规范、js规范。

到这全书就结束了。将学习笔记记录下来希望对看到该文的朋友有一定的帮助。O(∩_∩)O~ 

转载请注明出处

原文地址:http://www.cnblogs.com/Joans/archive/2012/09/14/2685110.html

编写高质量代码:Web前端开发修炼之道(四)的更多相关文章

  1. 编写高质量代码:Web前端开发修炼之道(一)

    最近老大给我们买来一些技术方面的书籍,其实很少搬着一本书好好的完整的看完过,每每看电子档的,也是打游击式的看看这章,瞅瞅那章,在那5本书中挑了一本比较单薄的<编写高质量代码web前端开发修炼之道 ...

  2. 编写高质量代码:Web前端开发修炼之道(三)

    第五章:高质量的Javascript 这章的内容我看的最久,这是跟我js基础没打好有着莫大的关系,但是还是耐着性子看完了, 不懂的东西都是百度上搜索,理解后再继续.下面是记录下来的笔记. 1)如何避免 ...

  3. 编写高质量代码:Web前端开发修炼之道(二)

    第四章:高质量的css 1)怪异模式和标准模式 在标准模式中,浏览器根据规范表现页面:而怪异模式通常模拟老式浏览器的行为以防止老站点无法工作. 他们两者之间的差异比较典型的表现在IE对盒模型的解析:在 ...

  4. 《编写高质量代码——Web前端开发修炼之道》读后随笔

    结构样式行为的分离 结构标准包括XML标准.XHTML标准.HTML标准:样式标准有CSS标准:行为标准主要包括DOM标准和ECMAScript标准. 通常的项目会按照如上的方式进行分离,但自己曾今做 ...

  5. 读《编写高质量代码-Web前端开发修炼之道》笔记

    第一章 1.Web标准由一系列标准组合而成,核心理念是将网页的结构,样式和行为分离,所以分为三大部分:结构标准,样式标准和行为标准.结构标准包括XML标准,XHTML标准,HTML标准:样式标准指CS ...

  6. 【读书笔记】读《编写高质量代码—Web前端开发修炼之道》 - JavaScript原型继承与面向对象

    JavaScript是基于原型的语言,通过new实例化出来的对象,其属性和行为来自于两部分,一部分来自于构造函数,另一部分是来自于原型.构造函数中定义的属性和行为的优先级比原型中定义的属性和优先级高, ...

  7. [已读]编写高质量代码--Web前端开发修炼之道

    我觉得还蛮实用的一本,推荐看看,主要涉及到这些: 标签语义化.css模块化. css的一些东西,比如haslayout 文档流,还有如何实现水平.垂直居中. js代码组织与js分层.js压缩 编码规范 ...

  8. 通用base.css —— 《编写高质量代码 web前端开发修炼之道》

    @charset "utf-8"; /*CSS reset*/ html{color:#000;background:#FFF;} body,div,dl,dt,dd,ul,ol, ...

  9. 『编写高质量代码Web前端开发修炼手册』读书笔记--高质量的CSS

    1.怪异模式和DTD 标准模式:浏览器根据规范表现页面 怪异模式:模拟老浏览器行为防止老站点无法工作(为了兼容老式浏览器的代码),如果漏写DTD(Document Type Definition文档定 ...

随机推荐

  1. 如何将.crt的ssl证书文件转换成.pem格式

    如何将.crt的ssl证书文件转换成.pem格式 摘自:https://www.landui.com/help/show-8127 2018-07-04 14:55:41 2158次 准备:有一台安装 ...

  2. ubuntu14.04下安装qt5

    1.sudo apt-get install build-essential 2.先打开终端快捷键ctrl+t 3. 然后输入: sudo apt-get install cmake qt5-defa ...

  3. Python自然语言处理工具NLTK的安装FAQ

    1 下载Python 首先去python的主页下载一个python版本http://www.python.org/,一路next下去,安装完毕即可 2 下载nltk包 下载地址:http://www. ...

  4. ubuntu-server部署php+mysql运行环境

    1.apt-get install git php5 mysql-server apache2 phpmyadmin 2.sudo ln -s /usr/share/phpmyadmin /var/w ...

  5. 如何快速增加pdf书签,解除pdf限制

    一.需要的工具 福昕PDF阅读器 Foxit PDF Editor 2.2.1 build 1119 汉化版 下载地址:http://www.onlinedown.net/soft/51002.htm ...

  6. MIDA Converter Basic patched for RAD Studio 10.1.2 Berlin (VCL转换到FMX)

    Mida is the only way to try to convert your project from VCL to FireMonkey. Version after version, M ...

  7. 如何让X5发现你的手机

    1. 手机开启 USB 调试.不用 ROOT.2. 装驱动.(问题就在这里) 首先要装对驱动,如果你的驱动叫 MyHTC,请立即删除. 找个 手机助手.例如 百度 腾讯 360 等等.反正不论你是谁的 ...

  8. 读取IE缓存文件

    使用WebCacheTool项目中的WinInetAPI.cs和Win32API.cs两个类 /// <summary> /// 获取IE缓存文件 /// </summary> ...

  9. 零成本实现WEB性能测试(二)JMeter基础知识

    特点: 支持多种服务类型进行测试,包括: Web-Http,HTTPS SOAP Database via JDBC LDAP JMS Mail-POP3 & IMAP 支持录制回放方式获取脚 ...

  10. Inno Setup卸载时注销bho

    Inno setup是一个制作安装包的免费工具,比如你用Qt开发完成一款软件,拿Inno setup打个安装包甩给客户安装就好了. 但是bho插件在注册后,万一用户卸载软件时,bho插件还是躺在管理加 ...