--- UBAO Team
--- Kate Lin
一、Target
掌握JS语言中比较容易误解的概念
二、Getting start – Why we need to study?
我第1次使用JS是在1个财务项目中。当用户在页面上填完借方所有科目及贷方所有科目的金额后,在焦点离开最后1个输入框时,程序需要自动累计出借方总金额和贷方总金额,并对比借方金额与贷方金额是否相等,如果不相等就给客户以提示。我们借助JS完成了这个当时看起来很酷的功能。之后JS又被我们大量的运用在表单的校验中-帮助用户以正确格式填写信息。事实上很多人对JS的应用,很长时间就停留在这种阶段-做1些页面上的校验、简单的事件处理的辅助性工作上。
但实际上JS可以做的工作远不止这些(也不会很多,但我相信大部分情况下会超越你的想象)。因为要知道光靠css和html,我们的页面是不可能动起来的!我们需要借助JS来与用户进行交互。其实在很早以前,在很多web应用中,JS就被用来编写客户端的1些常用组件。如菜单、树、Grid等等。虽然直到最近由于Ajax的热炒,这位默默无闻的小兵才从后台走向前台。
Ajax的使用,使某些web应用更易用、更人性化,同时带来了用户体验的提升。它所带来的局部刷新页面的方式,使得页面需要1次性载入的东西更少,每次与服务端交互完毕后返回的东西更少,需要更新的地方更少。合理的使用它对网站来说是大有裨益的(注意是合理,不是滥用。至于什么样是合理,应该是因时因地制宜。什么时候它应该发挥锦上添花的作用,什么时候它可以大规模的应用,取决于实际的项目环境)。
我们来看1些典型而成功的Ajax应用:
google的搜索提示。当我们敲入关键字的前几个字符,google会立即在下拉菜单里面为我们列出匹配的词条及相应的搜索结果。
chinaren网站的登陆。当我们输入完正确的用户密码后,页面登陆部分那个小区域会显示我们成功登陆的信息。
要做到这些其实并不复杂。Ajax并不是什么新发明的技术。它是1系列我们1直在用的技术的集合。它利用XMLHttpRequest进行异步数据获取; 利用文本或html或xml或json作为交互数据的载体; 利用css渲染返回的数据; 最后利用JS将以上这些过程串联起来处理。虽然说JS从语言自身来说存在着不少弊端,但依然有它的优势(在jdk1.6中甚至提供了在JAVA中编写JS代码的支持)。如果html的变革不那么迅速的到来。 在web2.0流行的今天,我们要做的就是掌握它的使用,合理的将它的优势发挥出来。
JS是门入手容易进阶难的语言,对知识点不够清楚的理解会导致编写复杂应用时的困难。因此我写这篇文档的原因,除了想整理1下自己所学。更是为了起抛砖引玉的作用,希望有高手能够写些深入的文章以省下我学习的时间,厚厚。个人的理解表达能力有限,有误的地方,欢迎大家补充纠正。
三、Syntax – explanation on easily confuse place
3.1 dataTypes and variable
学过编程的地球人都知道,每次我们开始学习1门语言,很多时候总是先学习它所支持的数据类型(变量可以看成是某种数据类型的实例)。 对于有编程经验的人来说,可能感觉很多语言支持的数据类型都是大同小异。这里还要罗嗦的讲这个部分是因为JS对变量的定义简单灵活而不严密,需要特别注意。
和JAVA等强类型语言不1样,JS使用方式var variableName = value; 定义变量。它并不把数据类型的声明作为变量声明的第1部分!(有时我写完JAVA代码再去写脚本时,常常会用int variableName = value; 在js里声明变量, 直到运行时报错才发现!!-_-—JS是解释型语言,不需要编译,很多错误只有到运行时才能发现,但现在有些IDE也会提供在编写代码时的语法检查,比如intelliJ)。
在强类型的语言社会里,1个变量它是什么打他出生那刻就确定了。如果规划他要当流浪汉,他就只能做流浪汉这1类的工作。如果有天他忽然想改行竞选当总统,除非总统继承自流浪汉或总统与流浪汉实现1样的接口,否则那是不可能的事。如JAVA那样的语言,在定义变量的时候必须明确的指定变量的类型。这很严密也带来了不方便。在这上面JS很民主,它提供了宽松的方式。1个变量究竟是什么类型,要看它被赋的值是什么类型。你还可以在代码的任何角落通过赋值把你的变量指向任何类型的值。不需要任何转型,不会出错!甚至它有七十二变的本事,在你需要它成为什么类型的时候,它能自动转型为你所期待的类型!
那么JS里究竟有哪些数据类型呢?以下给出的几种就是JS所支持的数据类型:
基本数据类型:数字、文本、布尔型。
小数据类型:undefined 、null。(所谓小,意思就是它只有1个值)
复合数据类型:对象 、数组(数组表现的行为与对象不同,所以虽然它其实也是1种对象,但仍把它独立当成1种数据类型)、函数。
Note: 这里有些容易误解的地方需要注意。比如函数是1种数据类型。Date、RegExp、Error是Js里的专用对象,而非数据类型。
函数作为1种数据类型正是JS灵活特征的体现之一。这意味着函数可以被存储在变量、数组、对象中,也可以作为参数进行传递。
alert(typeof undefined); // undefined
alert(typeof null); // object。null也是1种object类型。但是它并不具备object的特性。
var d = new Date();
alert(typeof d); // object。说明Date不是1种类型,只是1种专用对象
//存储在变量中的函数,因为这个函数没有名字,所以它也是1个匿名函数。
var v_f = function(){}
alert(typeof v_f); // function。 函数是1种数据类型
var arr = [new Function("alert(1+1);"), new Function("alert(2+2);")]; //存储在数组中的函数
alert(typeof arr); // object。数组是1种对象
arr[0](); //2
arr[1](); //4
var o = new Object();
o.m1 = function(){
return 'method';
}
alert(typeof o);// object
function handler(){
alert('handle event');
}
function callback(evtHandler){
evtHandler();
}
callback(handler); //将函数作为参数传递,是不是很酷?利用这种特性可以实现回调
3.2 auto datatype conversion
当某个类型的值被用于需要基它类型值的环境中时,JS会自动尝试将这个值转为所需要的类型。所以我们常常可以看到这样的用法:
var object = {};
if( object ){ //object自动转为true,不需要写成object != null
alert('object not null');
}
var b = new Boolean(false);
if( b ){ //b自转转为true
alert('expression is true');
}
执行的结果是打印
object not null
expression is true
产生这个结果的原因是非空的对象在需要布尔值的环境中会被转为true。要注意对原始值为false的包装对象也是如此。但如果用if( b = = true) 那么它就不会进if语句了。因为此时进行了运算。
3.3 global object
在执行JS代码之前,JS解析器将会先创建一个global object。在html文档中, window对象作为指向global object的一个引用,定义了全局的属性(如parseInt、setTimeout方法)。任何定义在函数体外,或函数体内没用var语句声明的变量都属于global object的属性。
3.4 scope chain
作用域链定义了JS代码查找变量的顺序。每个函数都有其执行的作用域链。作用域链是一个对象链。当JS代码需要查询1个变量的值时,它从链的第1个对象开始延着作用域链查询,直至找到变量的定义。一个函数的和用域链为 它自己调用对象全局对象。
var i = 0;
function out(){
function inner(){
//查找i的定义:inner-->out-->global.只要在某个位置找到就立即返回
alert(i);
}
inner();
}
out();
3.5 this, who are u point to?
在很多语言中,this都是重要且强大的关键字。在Java中,它总是指向当前的类的instance。但在JS里this总是指向它的东家,就是function的所有者。这个隐含的意思就是说如果function换了东家,this的引用也会随之改变。
在JS里定义的函数,如果没有指定调用者,则默认的它的所有者是一个隐含的全局对象(在html页面里,全局对象可以看作是window)。
var name = 'attribute in global'; //可以将这个变量看成是定义在全局对象里的属性
function Test1(){
alert('this point to '+(window == this? 'global' : 'local') + ': ' + this.name);
}
Test1(); //this point to global:attribute in global。没有指定它的调用者,所以这时this指向的是全局对象window。Test1里面打印的this.name即是全局对象的属性
function Test2(){
this.name = 'attribute in local';
alert('this point to '+(window == this? 'global' : 'local') + ': ' + this.name);
}
var t2 = new Test2(); // this point to local:attribute in local。这时this指向的是t2这个对象,所以Test2里面打印的是在Test2内定义的属性。
setTimeout(function(){alert('say hello!');} , 1000); //setTimeout是定义在全局对象里的方法,可以直接调用
所以当对你this的指向不知所以然时,很容易写出导致错误的脚本,如下例:
<div id="d3" onclick="handler()">click me and u will find error occur!!</div>
<script type="text/javascript">
function handler(){
this.style.color = 'red'; // will cause "this.style is null or not an object" error
}
</script>
在上面的例子中,程序员原本希望在单击层d3时将它的字体着色改成红色,但是不幸事与愿违,单击的时候错误产生了。为什么?因为此时this指向的是window对象(非层d3)。window对象是没有style属性的,所以Error就产生了。
是不是没听懂呢?那我们再说得更清楚些,看下例:
<div id="d1" onclick="handler()">click me and alert true</div>
<div id="d2">click me and alert false</div>
<script type="text/javascript">
function handler(){
alert(this == window);
}
document.getElementById('d2').onclick = handler;
</script>
在上例代码中,层d1采用inline event registration model来注册onclick事件。这种注册方式只是告诉浏览器,在单击d1的时候应该去触发函数handler。因此这时handler里的this仍指的是全局对象window。层d2使用脚本方式注册onclick事件。这时候函数handler被copy给了d2的onclick属性。因此在单击d2时,方法里的this指向的就是d2这个对象,而不再是全局的window对象了。
因此对于那个错误的例子,正确的处理方式如下。将this做为参数传给事件处理函数,或者在事件处理函数中通过document.getElementById来获取要操作的DOM元素d3。
<div id="d3" onclick="handler(this)">click me and change my color</div>
<script type="text/javascript">
function handler(divObj){
divObj.style.color = 'red';
//document.getElementById(‘d3’).style.color = ‘red’;
}
</script>
3.6 Function and Method
作为对象的属性的Function就是Method。但实际上当你直接调用1个Function时,你其实是在调用全局对象的Method。所以从这个角度上来说Function和Method没什么不同。实际上它们最大的不同主要在于设计意图上的不同。Method更多的是为了定义自定义类的行为,在方法体内,this指代的是调用它的,定义它的自定义类的实例。
3.7 Execution Context
执行上下文即JS代码执行的上下文环境。
3.8 apply &&call
如何调用1个函数?最简单的方法是用method ( arguments )。我们现在将介绍的两个方法也是用来调用函数的。但是它们比较另类,因为它们可以在调用函数的时候改变其其运行的上下文环境(改变函数的东家,记得上面说的吗,所以函数里面的this的指向也就随之改变)。这两个很cool的兄弟是apply和call。它们的格式如下:
invokedMethod.apply( invodeObject, [args]);
invokedMethod.call( invodeObject, args1, args2, .., argsN);
说明1下:invodedMethod是将被调用的函数。invodeObject是函数的新东家,args是被调用函数的参数。
为了容易理解,我写一个简单的例子:
var brand = ‘china’;
//定义1个将被调用的方法
function printBrand(computer){
//注意this的改变
alert(computer + ' use brand ' + this.brand);
}
function IBM(){
this.brand = 'ThinkPad';
}
function Lenovo(){
this.brand = 'Lenovo';
}
var ibm = new IBM();
var lev = new Lenovo();
/**
* apply与call相同处:
* 1、作用相同.都是使某个方法作为某个对象的方法运行.
* 2、第1个参数都是要调用该方法的对象。 *
* 不同处:
* 1、apply方法,第二个参数是数组或arguments类型的变量
* call方法第二个参数是以逗号分隔的任何变量
* 2、所有参数是都不是必选的。第1参数为空时,默认为window。
*
* plus不明白的看例子的输出就会明白了^^
*/
printBrand.apply(ibm, ['X2x']); // X2x use brand ThinkPad
printBrand.call(ibm, 'T2x'); // T2x use brand ThinkPad
printBrand.apply(lev, ['X6x']); //X6x use brand Lenovo
printBrand.call(lev, 'T6x'); // T6x use brand Lenovo
printBrand.call(); // undefined use brand china
以上的代码,其实相当于:
function printBrand(computer){
//注意this的改变
alert(computer + ' use brand ' + this.brand);
}
function IBM(){
this.brand = 'ThinkPad';
}
function Lenovo(){
this.brand = 'Lenovo';
}
var ibm = new IBM();
var lev = new Lenovo();
ibm.printBrand = printBrand; //将printBrand方法给ibm对象
lev.printBrand = printBrand; //将printBrand方法给lev对象
ibm.printBrand('X2x');
lev.printBrand('X6x');
看到这里,也许大家会想到利用这两个方法,我们就可以巧妙的实现JS类的继承。
function Parent(id){
this.id = id;
this.getLocation = function(){
alert(this.id + ' at XiaMen UBao');
}
}
function Child(id){
/**调用Parent这个Function。并用指向Child实例的this替换Parent里的this*/
Parent.apply(this, arguments);
//Parent.call(this, id);
}
var c1 = new Child('katelin');
c1.getLocation(); // 打印 'katelin at XiaMen UBao'
写到这里,我觉得自己可能说得太罗嗦了,上面说的都是比较容易搞错的地方,而且还有很多我自己也不是很清楚的未提及的地方。 希望大家自己看书,再把心得写出来分享。
四、Code Style
为什么说code style很重要。想想看也许在某个时候,由于你不小心少打了一个分号,你的代码又被去掉了换行符压缩了。拜IE所提供的基本上没用的错误信息,我们将不得不用肉眼从那1行长得没有尽头的代码里面找出错误的根源,那将是多么可怕的1件事-_-!!(我就曾经遭遇过。最后我花了1晚上才找出没加分号的那行。自从那次后,我写脚本时都很老实的在每行后面加上分号)。
好的代码风格不仅减少错误的发生机率,也为后面维护的人留下方便之门。通过对语法的深入了解和实践的累,我们可以整理出1些好的编码风格并形成良好的编程习惯。有时候这也是经验的1种体现。
1. 尽量将变量的声明集中放在函数体的头部
2. 在每行的末尾加上分号;
3. if和else后面的语句用{}括起来
4. 使用/**/添加注释
五、Tips
1. 拼装大的字符串,尽量少用“+”符,尽量使用数组。
在开发动态页面的过程中,我们经常要拼装html,有时候我们还需要拼装要提交的数据。如果直接用操作符“+”进行字符串连接操作,它的效率是不高的。
你可能会问为什么不高捏?我想大概因为当我们使用“+”符时,JS会为字符串内部创建一个瞬态的String包装对象。这种频繁的创建,丢弃可能是导致性能不高的原因。所以推荐使用数组来处理大字符串连接。
function StringBuffer(str){
var arr = [];
if(str) {
arr[0] = str;
}
this.pos = arr.length;
this.append = function(s){
arr[this.pos++] = s;
return this;
}
this.toString = function() {return arr.join("");}
this.clear = function(){arr = [];}
六、Better Design - Three Layer Model
J2EE的前端开发,即web页面的开发,经常是让人非常诟病的地方。混杂着大量的css,html,js,java代码的页面常常让维护的人员无所适从。所以说对于大型的web应用的前端开发来说,在开发前需要对页面做合理的分层。制定清淅可行的规范,以降低之后的维护成本。我们1般会将页面分为三层,这也是比较清楚的1种实践。
内容 :这是静态的html文本数据。
展示:通过css对html文本进行渲染以提高页面的观感。
动作:通过脚本来控制用户的交互过程。
下周有时间再写1点关于Ext的
分享到:
相关推荐
本文所提及的Emilia Fridman所著的《Introduction to Time-Delay Systems Analysis and Control》就是这类学术专著的代表。此书在系统与控制领域具有重要的学术地位,提供了关于时间延迟系统的深入分析和控制策略的...
Wireless networks are under constant pressure to provide ever higher data rates to increasing numbers of users with greater reliability. Space-time processing technology, which uses multiple antennas ...
CUDA for Engineers An Introduction to High-Performance Parallel Computing 英文azw3 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
Arogyaswami Paulraj和Rohit Nabar,Dhananjay Gore著的《Introduction to Space-Time Wireless Communications》教材课件,原版的课件。通俗易懂
混合信号集成电路测试与测量是微电子领域的一个重要分支,该领域的书籍《An Introduction to Mixed-Signal IC Test and Measurement》(混合信号IC测试与测量简介)作为学习IC测试的经典教材,提供了深入浅出的理论...
Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process, Second Edition
an-introduction-to-optimization-4th-edition-solution-manual 为an introduction-to-optimization-4th-edition 的习题解答,高清英文完整版本
Introduction to Agent-Based Modelling. The overarching aim of this chapter is to give the reader an understanding of what an agent-based model is.
Pragmatic AI An Introduction to Cloud-Based Machine Learning 2018
CUDA for Engineers An Introduction to High-Performance Parallel Computing 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
《机器人学导论 - 机械与控制》是由John J. Craig编写的教材,此书的第三版在原有内容基础上进行了更新和扩充,尤其增加了许多与Matlab相关的练习题目。这本书是机器人学领域的经典教材,它不仅仅介绍了机器人学的...
For many years all three of us have been interested in, and have tried to make contributions to, derivative-free optimization. Our motivation for writing this book resulted from various circumstances....
iterative, and skillful agile modeling practices. <br>Developers and students will learn object-oriented analysis and design (OOA/D) through three iterations of two cohesive, start-to-finish case ...
### 热力学与热平衡统计学导论 #### 标题解读 - **热力学**:一门研究能量转换及物质系统状态变化规律的物理学科。 - **热平衡统计学导论**:介绍如何通过统计方法来理解大量粒子系统的宏观性质。...
Introduction-To-The-Theory-Of-Computation-Michael-Sipser.pdf
An Introduction to the Event-Related Potential Technique.PDF 是一个STEVEN J。LUCK的经典ERP实验指导书,2009年由范思陆翻译成中文,华东师范大学出版《事件相关电位基础》
An Introduction to Network Slicing 1 Introduction 2 1.1 Abbreviations 3 1.2 Network Slicing: The Concept 3 2 Defining a Network Slice 4 3 The Network Slicing Blueprint 8 4 What can Network Slicing 12 ...
Introduction-to-Digital-Filters-with-Audio-Applications