??xml version="1.0" encoding="utf-8" standalone="yes"?> 在?span style="font-family: 'Courier New';">java~程思想》中q样定义 异常Q阻止当前方法或作用域l执行的问题。虽?span style="font-family: 'Courier New';">java中有异常处理机制Q但是要明确一点,决不应该?/span>"正常"的态度来看待异常。绝对一点说异常是某种意义上的错误Q就是问题,它可能会DE序p|。之所?/span>java要提出异常处理机Ӟ是要告诉开发h员,你的E序出现了不正常的情况,h意?/span> 记得当初学习java的时候,异常L搞不太清楚,不知道这个异常是什么意思,Z么会有这个机Ӟ但是随着知识的积累逐渐也对异常有一Ҏ觉了。D一个例子来说明一下异常的用途?/span> 看一下这个类中关于除q算的方法,如果你是新手你可能会直接q回计算l果Q根本不去考虑什么参数是否正,是否合法Q当然可以原谅,谁都是这栯来的Q。但是我们应可能的考虑周全Q把可能DE序p|?span style="font-family: 'Courier New';">"苗头"扼杀在摇中Q所以进行参数的合法性检查就很有必要了。其中执行参数检查抛出来的那个参数非法异常,q就属于q个Ҏ的不正常情况。正常情况下我们会正的使用计算器,但是不排除粗心大意把除数赋gؓ0。如果你之前没有考虑到这U情况,q且恰y用户数学基础不好Q那么你完了。但是如果你之前考虑Cq种情况Q那么很昄错误已在你的掌控之中?/span> 二. 异常扫盲行动 今天和别天时看到一个笑话:世界上最真情的相依,是你?span style="font-family: Tahoma;">try我在catch。无Z发神马脾气,我都默默承受Q静静处理?/span> 大多数新手对java异常的感觉就是:try...catch...。没错,q是用的最多的Q也是最实用的。我的感觉就是:java异常是从"try...catch..."走来?/span> 首先来熟悉一?span style="font-family: 'Courier New';">java的异怽p: Throwable cL Java 语言中所有错误或异常的超c?/span>Q这是一切皆可抛的东西)。它有两个子c:Error?/span>Exception?/span> ErrorQ?/span>用于指示合理的应用程序不应该试图捕获的严重问题。这U情冉|很大的问题,大到你不能处理了Q所以听之Q之就行了Q你不用它。比如说VirtualMachineErrorQ当 Java 虚拟机崩溃或用尽了它l箋操作所需的资源时Q抛错误?/span>好吧Q就这个异常的存在了,那么应该何时Q如何处理它呢?Q交l?span style="font-family: 'Courier New';">JVM吧,没有比它更专业的了?/span> ExceptionQ?/span>它指Z合理的应用程序想要捕L条g。Exception又分Zc:一U是CheckedExceptionQ一U是UncheckedException。这两种Exception的区别主要是CheckedException需要用try...catch...昄的捕P?/span>UncheckedException不需要捕莗通常UncheckedException又叫?/span>RuntimeException。?/span>effective java》指出:对于可恢复的条g使用被检查的异常Q?/span>CheckedExceptionQ,对于E序错误Q言外之意不可恢复,大错已经酿成Q用运行时异常Q?/span>RuntimeExceptionQ?/span> 我们常见?span style="font-family: 'Courier New';">RuntimeExcepiton?/span>IllegalArgumentException?span style="font-family: 'Courier New';">IllegalStateException?/span>NullPointerException?/span>IndexOutOfBoundsException{等。对于那?span style="font-family: 'Courier New';">CheckedException׃胜枚举了Q我们在~写E序q程?/span>try...catch...捕捉的异帔R?/span>CheckedException?/span>io包中?/span>IOException及其子类Q这些都?/span>CheckedException?/span> 三. 异常的?/p>
在异常的使用q一部分主要是演CZ码,都是我们q_写代码的q程中会遇到的(当然只是一部分)Q抛砖引玉吗Q?/p>
?span style="font-family: 'Courier New';">1. q个例子主要通过两个ҎҎ来演CZ下有了异总后代码的执行程?nbsp; 首先指出例子中的不之处Q?span style="font-family: 'Courier New';">IndexOutofBoundsException是一个非受检异常Q所以不?/span>try...catch...昄捕捉Q但是我的目的是对同一个异常用不同的处理方式,看它会有什么不同的而结果(q里也就只能用它就一下了Q。异常出现时W一个方法只是蟩Ztry块,但是它后面的代码会照h行的。但是第二种׃一样了直接跛_了方法,比较强硬。从W一个方法中我们看到Q?/span>try...catch...是一U?/span>"事务?/span>"的保障,它的目的是保证程序在异常的情况下q行完毕Q同时它q会告知E序员程序中出错的详l信息(q种详细信息有时要依赖于E序员设计)?/span> ?span style="font-family: 'Courier New';">2. 重新抛出异常 异常的本意是好的Q让我们试图修复E序Q但是现实中我们修复的几率很,我们很多时候就是用它来记录出错的信息。如果你厌倦了不停的处理异常,重新抛出异常对你来说可能是一个很好的解脱。原不动的把这个异常抛l上一U,抛给调用q个Ҏ的hQ让他来费脑{吧。这L来,java异常Q当然指的是受检异常Q又l我们^d多麻烦,管它的出发Ҏ好的?/span> ?span style="font-family: 'Courier New';">3. 异常铄使用及异怸?/span> 定义三个异常c:ExceptionA,ExceptionB,ExceptionC 异常丢失的情况: Z么只是打印出来了ExceptionC而没有打印出ExceptionB呢?q个q是自己分析一下吧Q?/span> 上面的情늛当于了一U异常,q在我们排错的过E中非常的不利。那我们遇到上面的情况应该怎么办呢Q这是异常铄用武之地Q保存异怿息,在抛出另外一个异常的同时不丢失原来的异常?/p>
q个异常铄Ҏ是所有异常均具备的,因ؓq个initCause()Ҏ是从Throwablel承的?/span> ?span style="font-family: 'Courier New';">4. 清理工作 清理工作对于我们来说是必不可的Q因为如果一些消耗资源的操作Q比?span style="font-family: 'Courier New';">IO,JDBC。如果我们用完以后没有及时正的关闭Q那后果会很严重Q这意味着内存泄露。异常的出现要求我们必须设计一U机制不Z么情况下Q资源都能及时正的清理。这是finally?/span> 例子非常的简单,是一个读取文件的例子。这L例子?span style="font-family: 'Courier New';">JDBC操作中也非常的常见。(所以,我觉得对于资源的及时正确清理是一个程序员的基本素质之一。) Try...finallyl构也是保证资源正确关闭的一个手Dc如果你不清楚代码执行过E中会发生什么异常情况会D资源不能得到清理Q那么你qtry对这D?/span>"可疑"代码q行包装Q然后在finally中进行资源的清理。D一个例子: 我们注意一下这个方法和上一个方法的区别Q下一个h可能习惯更好一点,及早的关?span style="font-family: 'Courier New';">reader。但是往往事与愿违Q因为在reader.close()以前异常随时可能发生Q这L代码l构不能预防M异常的出现。因为程序会在异常出现的地方跛_Q后面的代码不能执行Q这在上面应l用实例证明q)。这时我们就可以?/span>try...finally来改造: 及早的关闭资源是一U良好的行ؓQ因为时间越长你忘记关闭的可能性越大。这样在配合?span style="font-family: 'Courier New';">try...finally׃证万无一׃(不要嫌麻烦,java是q么中规中矩)?/span> 再说一U情况,假如我想在构造方法中打开一个文件或者创Z?span style="font-family: 'Courier New';">JDBCq接Q因为我们要在其他的Ҏ中用这个资源,所以不能在构造方法中及早的将q个资源关闭。那我们是不是就没辙了呢Q答案是否定的。看一下下面的例子Q?/span> q一部分讲的多了一点,但是异常实是看hҎ用v来难的东西呀Q?span style="font-family: 'Courier New';">java中还是有好多的东襉K要深挖的?/span> 四. 异常的误?/p>
对于异常的误用着实很常见Q上一部分中已l列举了几个Q大家仔l的看一下。下面再说两个其他的?/p>
?span style="font-family: 'Courier New';">1. 用一?/span>Exception来捕捉所有的异常Q颇?/span>"一夫当关万夫莫开"的气。不q这也是最ȝ行ؓ?/span> 从异常角度来说这样严格的E序实是万无一失,所有的异常都能捕获。但是站在编Eh员的角度Q万一q个E序出错了我们该如何分L是到底是那引L呢,IOq是JDBC...所以,q种写法很值得当做一个反例。大家不要以U做法很q稚Q傻子才会做。我在公司实习时实看见了类似的情况Q只不过是h家没有用Exception而是用了Throwable?/span> ?span style="font-family: 'Courier New';">2. q里׃举例子了Q上面的E序都是反例。异常是E序处理意外情况的机Ӟ当程序发生意外时Q我们需要尽可能多的得到意外的信息,包括发生的位|,描述Q原因等{。这些都是我们解决问题的U烦。但是上面的例子都只是简单的printStackTrace()。如果我们自己写代码Q就要尽可能多的对这个异常进行描q。比如说Z么会出现q个异常Q什么情况下会发生这个异常。如果传入方法的参数不正,告知什么样的参数是合法的参敎ͼ或者给Z?/span>sample?/span> ?span style="font-family: 'Courier New';">3. ?/span>try block写的短,不要所有的东西都扔在这里,我们可能的分析出到底哪几行E序可能出现异常Q只是对可能出现异常的代码进?/span>try。尽量ؓ每一个异常写一?/span>try...catchQ避免异怸失。在IO操作中,一?/span>IOException也具?/span>"一夫当关万夫莫开"的气?/span> 五.ȝ ȝ非常单,不要Z使用异常而用异常。异常是E序设计的一部分Q对它的设计也要考究炏V?/p>
public class Calculator {
public int devide(int num1, int num2) {
//判断除数是否?
if(num2 == 0) {
throw new IllegalArgumentException("除数不能为零");
}
return num1/num2;
}
}
public static void testException1() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现?);
try {
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后Q后面的代码不能被执?
} catch (IndexOutOfBoundsException e) {
System.out.println("数组界错误");
}
System.out.println("异常出现?);
}
/*output:
异常出现?
数组界错误
4
异常出现?
*/
public static void testException2() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现?);
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后Q他后面的代码不能被执行
}
public class Rethrow {
public static void readFile(String file) throws FileNotFoundException {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.err.println("不知道如何处理该异常或者根本不惛_理它Q但是不做处理又不合适,q是重新抛出异常交给上一U处?);
//重新抛出异常
throw e;
}
}
public static void printFile(String file) {
try {
readFile(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
printFile("D:/file");
}
}
public class ExceptionA extends Exception {
public ExceptionA(String str) {
super();
}
}
public class ExceptionB extends ExceptionA {
public ExceptionB(String str) {
super(str);
}
}
public class ExceptionC extends ExceptionA {
public ExceptionC(String str) {
super(str);
}
}
public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
}
static void g() throws ExceptionC {
try {
f();
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
throw c;
}
}
public static void main(String[] args) {
try {
g();
} catch (ExceptionC e) {
e.printStackTrace();
}
}
}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:19)
*/
public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
}
static void g() throws ExceptionC {
try {
f();
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
//异常q?
c.initCause(e);
throw c;
}
}
public static void main(String[] args) {
try {
g();
} catch (ExceptionC e) {
e.printStackTrace();
}
}
}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:21)
Caused by: exception.ExceptionB
at exception.NeverCaught.f(NeverCaught.java:5)
at exception.NeverCaught.g(NeverCaught.java:10)
... 1 more
*/
public void readFile(String file) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
// do some other work
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void readFile() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work
//close reader
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile() {
BufferedReader reader = null;
try {
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work
// close reader
} finally {
reader.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class ResourceInConstructor {
BufferedReader reader = null;
public ResourceInConstructor() {
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream("")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public void readFile() {
try {
while(reader.readLine()!=null) {
//do some work
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void dispose() {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void readFile(String file) {
BufferedReader reader = null;
Connection conn = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
// do some other work
conn = DriverManager.getConnection("");
//...
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
]]>
Java NIO的高效得益于其两?/span>"助手"Q?/span>Channel(道)?/span>Buffer(~冲?/span>)。当然这两个"得力助手"?q龄"q远比java大!力求单易懂的把知识讲解给大家Q我举一个例子来说明一下这"两元大将"是如何在java NIO中配合工作的?/span>
中国古代有一U传l的吸烟器具---水烟袋。我想用q个东西来模拟一?/span>Channel?/span>Buffer的工作原理。不求说的好Q力求准无误?/span>
分析一下水烟袋是如何工作的Q?/p>
W一步,准备工作Q准备好上等烟丝Q第二步Q将"水斗"中装入适量的水Q烟仓中装满烟丝q插入水斗中Q然后再烟插入水斗中Q第三步Q点燃烟丝ƈ吸气。香烟从烟仓产生Q经q水的过滤进入水上的I闲区。第四步Qn受吸烟的快感.....从这个例子中我们提取Z要对?/span>"?/span>"Q来分析一下它的运动轨qV烟仓把烟生产出来,l过水的qo飘到水上面的I闲区域Q然后通过烟管q入人的体内?/span>
如果上面的过E大家理解了Q明白了Q那?span style="font-family: 'Times New Roman';">java NIO你已l了解了50%Q至你已经知道它的工作原理了。因为用NIO处理的数据和用水烟袋中吸烟很怼。我们分析一?/span>NIO的工作原理,非常单?/span>
当然和吸烟一h们首先必L要用NIO来处理需求的Ʋ望Q这好比你想要吸烟了Q,比方说我惌?/span>C盘下面的wk.txt文gq行备䆾Q备份文件的名称?/span>wk-bak.txt。类比刚刚吸烟的那个q程Q?/span>
步骤一Q准备工作,定文g的位|,q将E序不可直接操作的文件{换成字符的形式Q这一步和上边吸烟实例的第一步没有什么差别,只是q行一些简单的准备工作Q?/p>
String inFile = "C:\\wk.txt";
String outFile = "C:\\wk-bak.txt";
FileInputStream inf = new FileInputStream(inFile);
FileOutputStream outf = new FileOutputStream(outFile);
ByteBuffer buffer = ByteBuffer.allocate(1024);
步骤二:创徏文g输入道Q和文g输出道。(q一步与上边吸烟的第二部E有差别Q因?span style="font-family: 'Times New Roman';">Channel?/span>Buffer是在d的时候才发生?/span>"q接"动作Q?/span>
//准备文gd的管?->相当于烟仓和烟管
FileChannel inFc = inf.getChannel();
FileChannel outFc = outf.getChannel();
Charset charSet = Charset.forName("utf-8");
//q行~码解码-->相当于水斗中水的qo作用
CharsetDecoder decoder = charSet.newDecoder();
CharsetEncoder encoder = charSet.newEncoder();
步骤三:开始进行文件备份工作?/p>
while(true) {
//准备向Buffer中写入数?->相当于点燃烟丝,完事具备只欠东风
buffer.clear();
//q行字符~码 -->相当于水的过滤作?/span>
CharBuffer cb = decoder.decode(buffer);
ByteBuffer bb = encoder.encode(cb);
//数据l过~码以后暂存~冲?->相当于经q水qo后的烟暂停在水斗?/span>
int t = inFc.read(bb);
if(t == -1) {
break;
}
bb.flip();
//字节码写入目标文g-->相当于烟已经q入到嘴?/span>
outFc.write(bb);
}
步骤四:查文件是否备份成功。发?span style="font-family: 'Times New Roman';">C盘下面多了一?/span>wk-bak.txt的文Ӟ内容?/span>wk.txt一怸栗接下来享受java带给你的快感....
上面的例子估计大家已l理解的差不多了Q当然如果深I也会有一些不太妥当的地方Q但是不要较真,目的是学?span style="font-family: 'Times New Roman';">NIOQƈ不是吸烟。如果感觉你可以了那么就h上面的例子补充完_q行一下,享受一?/span>NIO的威武(当然字符~码q不是必ȝQ只是让q个例子昑־完整一点)?/span>
好吧如果你理解了上面的东西,q且真正的补全了文g备䆾的小E序Q那么就来进行稍微深入一点的学习吧?/p>
上文我提C丑烟的例子是有Ơ妥当的Q其中之一是Buffer的内部机制和"水斗"单的qo功能是不一L。还有字W编码那一块也不是?/span>Buffer内部实现的东西,decoder?/span>encoder是针?/span>Buffer的两个工兗那我们接下来分析一?/span>Buffer内部机制到底不一样在哪里呢(主要分析常用的两个方法;clear()Q?/span>flip()Q?
来吧Q打开Buffer的源码(摘取有用的部分)Q?/span>
public abstract class Buffer {
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
首先我们要明一点,所谓的~冲器仅仅是一?span style="font-family: 'Times New Roman';">"多功?/span>"的数l。可能在q个BuffercM没有体现Q但是如果我们打开ByteBuffer的源码会?/span>byte[]的数l,打开CharBuffer的源码会?/span>char[]的数l。因?/span>Buffer是所有缓冲器的父c,所以他它不能预计会有多种~冲器,所以烦性让"儿子"们自己实现去吧?/span>
既然知道了缓冲器是一?span style="font-family: 'Times New Roman';">"多功能的数组"Q那么我们用d的Ş式来分析一下上?/span>Buffer的源码?/span>
假设我们定义了一?span style="font-family: 'Times New Roman';">8个单位大的缓冲区Q如上图Q其?/span>Buffer也就是这么一个东西)。首先告诉大安三个重要的关于缓冲区状态的的属性:
capacityQ缓冲区的容量;
limitQ缓冲区q有多少数据能够取出或者缓冲区q有多少定w用于存放数据Q?/span>
positionQ相当于一个游标(cursorQ,记录我们从哪里开始写数据Q从哪里开始读数据?/span>
刚还说到flip()?/span>clear()?/span>Buffer的两个重要的ҎQ因为它们两个方法决定了~冲是否能正常的q行d工作?/span>
当我们要想从~冲Z写数据的时候必d执行flip()ҎQ当我们要想从缓冲区中读数据时必d执行clear()Ҏ?/span>
W一ơ向Buffer中写入数据时Q执行一?/span>flip()Ҏ以后Q?/span>Buffer的结构变成了q样Q?/span>position指向了第一个可以存取数据的0号位Q?/span>limit?/span>capacity同时指向最高位?/span>
假如W一ơ我们向Buffer中写入了3单位的数据,我们再次执行flip()Ҏ?/span>Buffer的结构会变成上图的所C。但是经qflip()的改造后positionL指向Buffer中第一个可用的位置。那么,未执行flip()Ҏ以前position在哪里呢Q很单,指向最后一个数据的位置?/span>
当我们想要从Buffer中读取数据时Q执?/span>clear()ҎQ?/span>Buffer的内部结构变成了上图所C,position指向了可L据的首位Q?/span>limit指向了原?/span>position的位|?/span>
从上面的几幅图中我们看出Q?span style="font-family: 'Times New Roman';">capacity代表?/span>Buffer的容量是不变的,limit?/span>position的差L表示Bufferd以读的数据,或?/span>Buffer中可以写数据的容量。还?/span>positionL于{于limitQ?/span>limitL于{于capacity?/span>
其实到这里我们已l发玎ͼNIOq不?/span>IO那么复杂Q因?/span>IO 中的Decorator模式?/span>Adaptor模式实让我们一旉怸到头脑,但是熟悉了会感觉?/span>IO的设计之_?/span>
NIO中还有一个知识点是无阻塞的Socket~程Q这里就不说了,因ؓ比较复杂Q但是如果我们真正理解了Selectorq个调度者的工作Q那么无d的实现机制我们差不多掌握了Q复杂也是~码上面的事了?/span>
Javascript的语法特?/span>
Javascript是一门动态的Q弱cd的,Z原型的脚本语a。我们在一些网站上的一些漂效果(虽然很讨厌)Q图片切换效果,q有一些文本编辑器{等Q这都要归功?/span>Javascript。当?/span>Javascript又是一个彻底的面向对象的语aQ虽然你看到的是遍地?/span>functionQ)Q但是谁有规定函C能是对象呢。下面来看一些具体的内容?/span>
Javascript基本语法
但凡有一点编E基的h都会觉得Javascript的语法很单,非常Ҏ上手Q但qƈ不代?/span>Javascript很容易学习,_N?/span>Javascript也不是一件易事?/span>Javascript有五U基本的数据cdQ数|NumberQ,字符ԌStringQ,布尔cdQ?/span>booleanQ,NullcdQ?/span>Undefinedcd?/span>
上面已经说过?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">Javascript
是一U动态的q型语aQ那我们来看看Javascript动态体现在哪里Q弱cd又体现在哪里Q?/span>//声明变量 var attr1 = 1; var attr2 = 1.03; var attr3 = "hello"; var attr4 = false;
不用?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">java
中那P惛_明什么类型的变量q必L前定义,?/span>Javascript中,我们"信手拈来"可以了Q它是什么样它就是什么类型。口说无凭,有代码有真相。我们可以通过Javascript?/span>typeof关键字来试Q一试便知?/span>//声明变量 var attr0 ; var attr1 = 1; var attr2 = 1.03; var attr3 = "hello"; var attr4 = false; alert(typeof attr0); //undefined alert(typeof attr1); //number alert(typeof attr2); //number alert(typeof attr3); //string alert(typeof attr4); //boolean alert(typeof null); //object alert(typeof undefined); //undefined
q里也还有一个知识点是关?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">null
?/span>undefined的?/span>Null是一个空的对象,的的cd?/span>ObjectQ?/span>undefined是全局对象Q?/span>WindowQ的一个属性,所以他的类型还?/span>undefined。但?/span>undefined是从nulll承来的?/span>Javascript的基本语法非常的单,大致览可以上手,所以其他的东西׃在这里说了。开始下一节...Javascript作用?/span>
Javascript的作用域是非怸性的Q我们先来看几个例子体验一下?/span>
// 作用? var outer = 1; function layer() { var layer1 = 2; function inner() { var layer2 = 3; alert(layer1);//2 alert(layer2);//3 } inner(); } layer(); alert(outer);//1 alert(layer1);//layer1已经被回? alert(layer2);//layer2已经被回?
q个是和其他~程语言怼的地方,主要涉及全局变量和局部变量;全局变量和局部变量的作用范围既不用细说了吧?/p>
// sample2 var x = "smile"; var alerts = function() { alert(x); //undefined var x = "fuck"; alert(x); //fuck //上面的相当于下面的代? //var x ; //alert(x); //undefined //x = "fuck"; //alert(x); //fuck }
Javascript没有块作用域,函数中声明的所有变量无论是在哪里声明的Q在整个函数中都有意义。估计对于用?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">java
语言的程序猿q一Ҏ不容易接受的Q反正我是这栗还有一个比较灵zȝ地方Q未使用var声明的变量都是全局变量Q而且全局变量都是WindowҎ的属性。呵?/span>...又纠l了Q适应好了!Q?/span>Javascript 的闭?/span>
在实现深U束Ӟ需要创Z个能昑ּ表示引用环境的东西,q将它与相关的子E序捆绑在一Pq样捆绑h的整体被UCؓ闭包。单从这样一个定义上说我们ƈ不容易理解什么是闭包。拿一个例子说?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">...
//闭包演示 var func = function() { var attr = "can read me??"; return function() { alert(attr); } } func()();
本来我们已经无法?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">func
函数的外面访问到attr属性,但是"can read me??"确实实通过alertQ)Ҏ弹出来了Q这是ؓ什么呢Q难道最后那个当做返回值的匿名函数帮我们保存了attr属性?当然调用此函数的方式也有一些奇怪:func()()。我们做q一步详l的介绍?/span>当调用一?nbsp;Javascript 函数Ӟ该函数就会进入相应的执行环境。如果又调用了另外一个函敎ͼ或者递归地调用同一个函敎ͼQ则又会创徏一个新的执行环境,q且在函数调用期间执行过E都处于该环境中。当调用的函数返回后Q执行过E会q回原始执行环境。同时创建的执行环境会包含一个作用域链,q个作用域链是通过该执行环境的活动(可变Q对象添加到保存于所调用函数对象?nbsp;[[scope]] 属性中的作用域铑։端而构成的?/p>
l合上面的例子简单分析一下,func()函数q回了一个匿名的函数functionQ所以被q回的匿名函C的执行环境和作用域链不会被回Ӟ当我们访?/span>attr属性的时候,我很会直接到functionq行环境的作用域链中L找。(对于q块内容涉及?/span>Javascript内容比深奥,也不怎么理解Q不q可以参考:http://www.cn-cuckoo.com/2007/08/01/understand-Javascript-closures-72.html Q?/p>
Javascript面向对象 Javascript的面向对象真是有点诡异,因ؓJavascript是一个函数式~程语言Q虽然我们可以模拟承,装{面向对象的Ҏ,但是L不如javaq样的语a感觉更自Ӟ当然不排除自q主观因素。我们先来模拟一?/span>Javascript的面向对象,体验一下?/span> 方式一Q最原始的方?/p>
方式二:q用工厂 方式三:q用构造函?/span> 方式四:q用原型方式 方式五:混合构造函数和原型方式 方式六:动态原型方?/span> 方式七:混合工厂 毕竟面向对象只是一U编E的思想Q用的多了其义自玎ͼ因ؓ自己没有学习多长旉?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">Javascriptvar car = new Object();
car.color = "red";
car.speed = 100;
car.showColor = function() {
alert(this.color);
};
car.showColor();
function createCar() {
var car = new Object();
car.color = "red";
car.speed = 100;
car.showColor = function() {
alert(this.color);
};
return car;
}
var car = createCar();
car.showColor();
function Car(color, speed) {
this.color = color;
this.speed = speed;
this.showColor = function() {
alert(this.color);
};
}
var car = new Car("blue", 400);
car.showColor();
function Car() {
}
Car.prototype.color = "blue";
Car.prototype.speed = 300;
Car.prototype.showColor = function() {
alert(this.color);
};
var car = new Car();
car.showColor();
function Car(color, speed) {
this.color = color;
this.speed = speed;
this.drivers = new Array("mike", "sue");
}
Car.prototype.showColor = function() {
alert(this.color);
};
var car1 = new Car("green", 300);
car1.drivers.push("wangkang");
car1.showColor();
alert(car1.drivers.join());
var car2 = new Car("black", 300);
car2.showColor();
alert(car2.drivers.join());
function Car(color, speed) {
this.color = color;
this.speed = speed;
this.drivers = new Array("mike", "sue");
}
if (typeof Car._initialized == "undefined") {
Car.prototype.showColor = function() {
alert(this.color);
};
Car._initialized = true;
}
var car1 = new Car("green", 300);
car1.drivers.push("wangkang");
car1.showColor();
alert(car1.drivers.join());
var car2 = new Car("black", 300);
car2.showColor();
alert(car2.drivers.join());
function Car() {
var car = new Object();
car.color = "red";
car.speed = 100;
car.showColor = function() {
alert(this.color);
};
return car;
}
var car = new Car();
car.showColor();
只是l大家进行一?span style="border-style: initial; border-color: initial; font-family: 'Times New Roman'; border-width: 0px; padding: 0px; margin: 0px;">Javascript
的扫Ԍ所以力求文章中没有错误Q思想了一点,例子多了一点!q有那一片推荐的博客希望大家认真的琢几遍,如果理解了那博客那?/span>Javascript的作用域Q闭包,面向对象{特性就非常Ҏ理解了?/span>http://www.cn-cuckoo.com/2007/08/01/understand-Javascript-closures-72.html