历史:ECMAscript开始与web没有依赖关系,web浏览器是ECMA实现可能的宿主环境之一,其他宿主环境还有Node(服务端的javascript实现平台),和Adobe Flash
本章内容 语法 数据类型 流控制语句 函数
目前 ECMA-262定义的第三版是各个浏览器实现最多的一个版本,第五版是接下来的实现。到2011年底还没完全实现,本文以第三版为基础,并以第五版变化作出说明
一。语法
1.区分大小写
2.标示符-变量,函数,属性,参数的名字
@首字母是字母、下划线或者美元符号$
@其他可以使字母、数字、下划线、和$
@不能用关键字、保留字、true,false、和null做标示符
3.注释
// 单行注释
/*
*
*
*/ 块注释
4.严格模式
ECMAscript 5引入,是一种定义不同的解释和执行模式,把ECMAscript 3不确定的行为处理掉,而且某些不安全的操作也抛出错误,启用办法是顶部添加
"use strict"
在函数内部也可以,如
function aa(){
"use strict"
//函数体
}
5.语句
@ ;结尾
@ 代码块,如
if(true){
}
6.关键字和保留字
7.变量
ECMAscript的变量是松散类型(就是可以保存任何类型的数据),用var来定义
@ var mes --mes为undefined
@ var mes=“hi”; mes=11; --可以,但是不推荐
@注意,用var操作符定义的变量将成为定义该变量的作用域中的局部变量
如在函数里面
1.
function a(){
var mes="HI";//局部变量
}
alert(mes);//错误
2.
function a(){
mes="HI";//全局变量
}
alert(mes);// "HI"
省略了var,默认成了全局变量,但是不推荐
@一条语句定义多个如
var mes="hi",
found=11,
age=false;
@严格模式下,不能为eval或者arguments定义变量
8.数据类型
@5种简单数据类型
Undefined
Null
Boolean
Number
String
@1种复杂类型
Object
@typeof操作符---对于一个值使用typeof操作符可能使用下面字符串
"undefined"-------该值未定义
"boolean" -------布尔
"string" -------字符串
"number" -------数字
"object" -------对象
"object" -------Null
"function" -------函数
例子
var mes="aaaaaa";
alert(typeof mes); ---"string"
alert(typeof(mes)); --"string"
alert(typeof 95); --"number"
@typeof操作符的对象可以使变量或者数值字面量
@typeof是操作符而不是函数,所以括号不是必须的
@@有时候typeof会返回一些疑惑但是技术上正确的值
@typeof null返回object,因为null被认为是一个空对象引用
@有些浏览器(Safai5-或Chrome7-)使用typeof 正则表达会返回function ,其他则object
@@技术角度上,函数在ECMA中script中时对象,不是一种数据类型,因此用typeof区分函数和其他对象
8.数据类型-Undefined
@只有一个值就是undefined
@使用var声明但是未加以初始化时就是undefined
1.
var mes;
alert(mes==undefined) --true;
2.
var mes=undefined;
alert(mes==undefined) --true;
3.
var mes;
alert(mes) --“ undefined”
alert(age) -- 报错
注意未声明和为初始化的概念
@@困惑的是
4.
var mes;
//下面变量为声明
// age
alert(typeof mes) --"undefined";
alert(typeof age) --"undefined";
对于未声明和为初始化都返回undefined
@@所以运用上面这点最好显示初始化变量是最好的明确选择,因为这样,当typeof就会返回undefined字符串,那么我们就知道该变量没有被声明而不是未初始化
如
var me==“”;
//下面变量未声明
// age
alert(typeof mes) --"String";
alert(typeof age) --"undefined"; 因为所有变量都初始化了,所以放回undefined肯定是未声明,而且这样不会报错
8.数据类型-Null
@也是只有一个值-null
@是一个空对象引用所以typeof Null是"object"
@实际上,undefined值是派生于null的,所以
alert(null==undefined); //true
@如果定义的是对象,最好先赋值为null,因为只需要检查null就知道已经是否保存一个对象的引用
var car=null;
if(car!=null){
}
@@无论在什么时候没必要把一个值显示设置为undefined,
@@null却相反,只要为明确保存什么对象时候,则设置为null
@@有助于区分null和undefined。
8.数据类型-Boolean
@只有两个值 true、false
@与数字值不是一回事,true不一定等于1,false不一定等于0
@区分大小写,True和False是标示符
@ECMA所有值都与Boolean有等价的值,可以使用Boolean()转换函数
如
var mes="hello";
var a= Boolean(mes);
规则
数据类型 |
转为true |
转为false |
Boolean |
true |
false |
String |
非空字符串 |
""(空字符串) |
Number |
非0,包括无穷大 |
0和nan |
object |
任何对象 |
null |
Undefined |
n/a |
undefined |
@if语句自动执行Boolean转换
var mes="DF";
if(mes){
}
8.数据类型-Number
@整数和浮点型
@十进制,八进制,16进制
八进制第一位为0,后面为0到7,超过则前导0被忽略,后面为实际你只解释
var a=070 //八进制 56
var b=079 //八进制无效,解释为十进制 79
十六进制前面为0x,后面0到9,a到f(可以大写)
var a =0xA --十六进制的10
var b=0x1f ----、十六进制的31
在进行算术计算时,所有八进制十六进制的值都会转换成十进制数值
@浮点数
var a=1.1;
var b=.1; --有效但是不推荐
@由于浮点数需要的内存空间是整数值的两倍,所以ECMAscript有时会把 浮点数转换为整数值
var a=1. 解释为1
var b =10.0; 解释为10
@科学计数法
var a=3.125e7 等于31250000
@@浮点数的精度为17位小数,进行算术计算时精确到远远不够整数
0.1+0.2不是0.3,而是 0.3000000000000004
所以
if(a+b==0.3){
alert("you got 0.3");
}
永远不会成立,不要这样做
@数据范围
1.Number.MIN_VALUE和Number.MIAX_VALUE,超出这两个范围则转换Infinity 正无穷 - Infinity 负无穷
2.Infinity 正无穷 - Infinity 负无穷 ,某次计算返回这两个数,则无法参数下次计算
判断处于最大和最小范围之间可以使用isFinite()函数
var a=Number.MIAX_VALUE+Number.MIAX_VALUE;
alert(isFinite(a));//false;
@NaN值-非数值
1。任务语言除以0都会报错,停止程序
2。ECMAscript中 则返回NaN,而不会停止
3。NaN不等于NaN alert(NaN==NaN);--false
4。isNaN 判断这个数是否"不是数值",
如
alert(isNaN(NaN) ) //true
alert(isNaN(10)) //false 10是一个数值
alert(isNaN("10") ) //false 可以转换成10
alert(isNaN("blue") ) //true 这个字符不能转换成数值
alert(isNaN(true) ) //false 可以转换成1
@@ isNaN也可以用于对象,首先调用对象的valueof(),确定是否能返回转换成数值,若不能,基于这个返回值再调用toString()方法,再测试返回值。
@转换函数
Number() 任何数值
ParseInt() 把字符串转换成数值
parseFloat() 把字符串转换成数值
@@Number() 转换规则
1.若Boolean 则转换成0和1
2.若数字值,不变
3.null 则0
4.undefined 则NaN
5.对象则首先调用对象的valueof(),确定是否能返回转换成数值,若不能,基于这个返回值再调用toString()方法,再测试返回值
5.字符串则如下
1.只包含数字(带正负),则转换为十进制,1--1, 123--123, 011--11
2.浮点和上面一样
3.若十六进制,0xf 则转换成十进制
4.空字符串,则为0
5. 其余则NaN
如下
var a=Number("DFSDF" ) --NaN
var b=Number("" ) -- 0
var c=Number( "000011") -- 11
var d=Number( true) --1
@@ParseInt() 转换规则
1.忽略前面空格,找到第一个字符串,若不是数字或者正负号,则NaN
2.如果第一个是数字,则一直解释下去,直到解释完或者遇到非数字
如1234aaa则转换为1234
22.5则转换为22
3.八进制,十六进制也能识别(严格模式会有问题)所以增加参数ParseInt(a,b),a为要转换的值,b为进数
var a=ParseInt("10",2) 10按二进制
var b=ParseInt("10",8) 10按八进制
var c=ParseInt("10",10) 10按十进制
var d=ParseInt("10",16) 10按十六进制
因为在严格模式ParseInt() 转换会造成混乱,所以最好加上参数
@@ParseFloat() 转换规则
1.和ParseInt一样,不过第一个小数点有效,第二个无效,如22.34.5转换为22.34
2.只解释10进制,所以没有第二个参数
3.如果字符窜包含一个可解释为整数的数(没有小数点或小数点后都是0),ParseFloat() 会返回整数
var a=ParseFloat"1234aaa") //1234
var b=ParseFloat("0xA") // 0
var c=ParseFloat("22.5") //22.5
var d=ParseFloat(22.334.5) // 22.334
var e=ParseFloat("0987.4") //987.4
var f=ParseFloat("3.125e7") // 31250000
8.数据类型-String
@String类型用于表示0或多个 16位Unicode字符组成的字符序列------字符串
@""或‘‘都一样,PHP则不同
@字符字面量--转义序列
字面量 |
含义 |
\n |
换行 |
\t |
制表 |
\b |
空格 |
\r |
回车 |
\f |
进纸 |
\\ |
斜杠 |
\‘ |
单引号,在用单引号表示的字符串中使用,如‘He said,\‘HEY.\‘‘ |
\" |
双引号,在用双引号表示的字符串中使用,如"He said,\"HEY.\"" |
\xnn |
以十六制代码nn表示一个字符(n为0到F)。例如,\x41表示"A" |
\unnnn |
以十六制代码nnnn表示一个Unicode字符(n为0到F)。例如,\u03a3表示希腊字符"Σ" |
@任何字符串长度都可以用length属性获取长度(如果字符串包含双字节字符,那么可能不会精确)
@ECMAScript 中字符串是不变的。创建之后若改变则先销毁再填充
@转换为字符串
1.toString(),几乎每一个值都有该方法,但是 null,undefined 没有该方法
数字的时候可以加入参数指定二进制八进制十进制十六进制
var a=10
a.toString() --10
a.toString(2) -- 1010
a.toString(8) --12
a.toString(10) --10
a.toString(16) --a
2.String(),任何类型都可以包括null,undefined
1.如有有toString(),则调用
2.如果是null,则返回"null"
3.如果是undefined,则返回"undefined"
@最简单的转换时直接与字符串""相加
8.数据类型-Object
@一组数据和功能的集合--var 0=new Object();
@是所有它的实例的基础,其中包裹一下方法
1.constructor:保存用于创建当前对象的函数,var 0=new Object();构造函数就是Object();
2.hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。参数必须是字符串,如:o. hasOwnProperty("name");
3.isPrototypeOf(Object):用于检查传入的对象是否是传入对象的原型
4.propertyIsEnumerable(propertyName):检查指定属性是否能用for-in语句,参数为字符串
5.toLocalString()
6.toString()
7.valueOf():返回对象的字符串、数值或布尔值表示
@@宿主对象可能继承也可能不继承Object,浏览器中的对象,如BOM和DOM中的对象都是宿主对象
5.操作符
5.1一元操作符
5.2位操作符
5.2布尔操作符
@一共有三个 非、与、或
@逻辑非 用!表示
1.与任何值都能返回一个布尔值,先转换为布尔值再求反
2。规则
&如果是对象,则false
&如果是空字符串,则true
&非空字符串,则false
&数值0,true
&非0包裹Infinity,则false
&null,true
&NaN,true
&undefined,true
如:
alert(!0) true
alert(!NaN) true
alert(!123) false
@逻辑与 用&& 表示
1.可以应用任何类型的操作数,不仅仅是布尔值
2.在有一个操作数不是布尔值的情况下,逻辑与操作不一定返回布尔值,一下规则
&如果第一个操作数对象,则返回第二个操作数
&如果第二个操作数是对象,则只有第一个操作数为true的情况下才会返回该对象
&如果两个操作数都是对象,则返回第二个操作数
&如果有一个数为null,则返回null
&如果有一个数为NaN,则返回NaN
&如果有一个数为undefined,则返回undefined
3.逻辑与属于短路操作,如果第一个数能够决定结果,则不会对第二个求值
如
var a=true;
var b=(a&&bbbbbbbbbbbbb);bbbbbbbbbbb未定义会发生错误
若
var a=false;
var b=(a&&bbbbbbbbbbbbb);bbbbbbbbbbb未定义不会发生错误
@逻辑或 用||表示
1.与逻辑与类似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值
2.
&如果第一个操作数对象,则返回第一个操作数
&如果第一个操作数求值为false,则返回第二个操作数
&如果两个操作数都是对象,则返回第一个操作数
&如果有两个数为null,则返回null
&如果有两个数为NaN,则返回NaN
&如果有两个数为undefined,则返回undefined
3.也是短路操作
5.4
1.乘性操作符-- *
&处理特殊值遵守下列规则
1.如果两个值都是数值则常规计算,若超过ECMA范围,则Infinity和-Infinity
2.如果有一个是NaN,则结果是NaN
3.如果Infinity与0相乘,则NaN
4.如果Infinity与非0相乘,则是Infinity或者-Infinity
5.如果是Infinity与Infinity则Infinity
6.如果一个数不是数值,则在后台调用number()转换其数值,再计算
2
除法操作符-- 斜杠/
3
求模--%
5.5
1.加法操作符---+
如果都是数值则按照常规加法,然后根据下列返回
&如果一个为NaN,则结果为NaN
&如果Infinity加Infinity,则Infinity
&如果-Infinity加-Infinity则-Infinity
&如果Infinity加-Infinity 则NaN
如果有一个是字符串,那么按照下面
&如果两个操作数都是字符串,则前后拼接
&如果有一个是对象、数值或布尔值,则调用它们的toString()方法取得相应字符串值,如果按照前面字符串规则
&对于undefined和null,则分别调用string()函数取得字符串"undefined" 和"null"
alert(5+5); //10
alert(5+"5"); //"55"
2.减法操作符--- -
如果都是数值则按照常规加法,然后根据下列返回
&如果一个为NaN,则结果为NaN
&如果Infinity加Infinity,则NaN
&如果-Infinity加-Infinity则NaN
&如果Infinity加-Infinity 则Infinity
&如果-Infinity加Infinity 则-Infinity
如果有一个是字符串、布尔值、null或undefined,则在后台调用Number()函数将其转换成数值,再根据前面做减法,如果转换成NaN,则结果为NaN
&如果有一个是对象,则调用对象的ValueOf()方法以取得表示对象的数值,如果是NaN,则结果是NaN,如果对象没有ValueOf()方法,则调用其toString()方法并将其得到的字符串转换为数值
5-trur==4 因为true转换为1
NaN-1=NaN
5-3=2
5-""=5 因为""转换成0
5-"2"=3 因为2转换成2
5-null=5 因为null转换成0
@@如果两个操作数都是字符串呢?
5.6 关系操作符
@小于<, 大于>, 小于等于<=, 大于等于>=,这几个关系操作符都返回一个布尔值
var result=5>3 //true
var result=5<3 //false
@与ECMAscript与其他操作符一样,当操作数使用非数值时候也要转换或完成某些奇怪的操作,规则:
&如果两个都是数值则数值比较
&如果两个都是字符串,则按照字符串对应的字符编码值
&如果一个数十操作数,则将另外一个操作数转换为一个数值,然后数值比较
&如果一个操作数十对象,则调用这个对象的valueof()用结果按照前面比较,如果没有ValueOf方法,则调用toString(),并用得到结果执行比较
&如果一个是布尔值,则先转换成数值再比较
&&比较字符串时候,大写字母的字符编码全部小于小写字母的字符编码
var result ="Black" < "alphabet" //true
&&如果比较两个数字字符串
var result="23"<"3" //true,2的编码是50,3的编码是51
var result="23"<3 //false,字符23会转成23,数值与字符串比较时,字符串都会转换成数值
var result="a"<3 //false,因为"a"被转换成了NaN
var result=NaN<3 //false,因为任何操作数与NaN比较,结果都是false
var result= NaN >=3 //false
5.7
1.相等操作符
@相等和不相等 ==和!=
1.都会先转换操作数(强制转换),然后再比较相等性
在转换不同类型时候,要遵守下列
1.如果有一个操作数是布尔值,则比较前转换为数值----false转换成0,true转为1
2.如果有一个操作数是字符串,另外一个是数值,则先字符串转换成数值再比较
3.如果一个操作数是对象,另外一个操作数不是,则调用对象的ValueOf方法用得到的基本类型值再比较
另外
1.null和undefined是相等的
2.比较值钱不能将null和undefined转换成其他值
3.如果一个数是NaN,相等则返回false,不相等则返回true(两个操作数都是NaN,相等操作符也返回false,因为按规定NaN不等于NaN)
4.如果两个操作数都是对象,则比较他们是不是同一个对象,如果都是指向同一对象,则返回true,否则false
表达式 |
值 |
null ==undefined |
true |
"NaN"==NaN |
false |
5==NaN |
false |
NaN==NaN |
false |
NaN!=NaN |
true |
false==0 |
true |
true==1 |
true |
true==2 |
false |
undefined==0 |
false |
null==0 |
false |
"5"==5 |
true |
2.全等和不全等 === !==
@除了比较之前不转换操作数之外,全等与不全等没有什么区别
var result=("55"==55); ‘//true 因为转换后相等
var result=("55"===55) //false 因为不同数据类型不相等
@null==undefined会返回true,但null===undefined 返回false ,因为不同类型的值
5.8条件操作符
variable=boolean_expression ?trueValue:falseValue
如:
var max=(num1>num2) ? num1: num2;
5.9赋值操作符
5.10逗号操作符
@声明变量
var num1=1,num2=2.num3=3;
@
赋值-在用于赋值时,逗号操作符总会返回表达式中的最后一项,如
var num=(5,1,4,8,0);//num的值为0
6.语句
6.1 if 语句
@ECMAScript会自动调用Boolean()转换函数表达式
6.2 do - while
6.3 while语句
6.4 for语句
@
1.
var count =10;
for(var i=0;i<count;i++)
{
alert(i);
}
由于ECMAScript中不存在块级域,因此在循环内部定义的变量可以再外部访问,如
2.
var count =10;
for(var i=0;i<count;i++)
{
alert(i);
}
alert(i);//10
3.无限循环
for(; ;){
dosonmething();
}
6.5 for-in 语句
for(var propName in window){
dociment.write(propName );
}
如果迭代的对象的变量值为null或undefined,for-in语句会抛出错误
ECMAScript 5 更正了,但是为了兼容,循环时候做好判断
6.5 label语句
6.6break和continue语句
@与label语句联合使用
6.7 with 语句--
@将代码块的作用域设置到一个特定对象中
@定义with语句的目的主要是为了简化多次编写同一个对象
var qs=location.search.substring(1);
var hostName= location.hostname;
var url= location.href;
上面那几行代码包含location对象,使用with语句可以写成
with(location){
var qs=search.substring(1);
var hostName=hostname;
var url=href;
}
严格模式会语法错误,大量使用with会性能下降,还是建议不要用
6.8 switch语句---全等操作符
switch(i){
case 25:
case 35: //25和35 合并了
alert(111);
break;
case 45:
break;
default:
alert("default");
}
@ECNAScript 相比其他语言,可以再switch语句中使用任何类型,无论是字符串还是对象都可以
@case的值不一定是常量,也可以是变量甚至表达式
var num=25;
switch(true){
case num <0:
alert(0);
break;
case num <=10 && num >0:
alert(1);
break;
default:
alert(2);
}
7.函数
1.
function Name(arg0 ,arg1,.......argN){
statements
}
@ECMAScript 中的函数在定义时不必制定是否返回值
@ 另外return 语句也可以不带任何返回值,这种情况下,函数停止执行后将返回undefined值
function Name(arg0 ,arg1,.......argN){
retrun;
}
@推荐做法要么永远返回值,要么永远不返回,否则会混乱
严格模式下限制
1.不能把函数命名为eval或arguments;
2.不能把参数命名为eval或arguments;
3.不能出现两个命名参数同名的情况
2.参数
@即便你定义的函数只接收两个参数,调用函数的时候未必一定传2个函数,可以传1,个或者3个,4个
@ECMAScript 中的参数在内部是用一个数组来表示,函数接收这个数组,而不在乎有多少个元素
@实际上,在函数体内可以通过arguments对象来访问这个参数数组
@其实arguments对象只是与数组类似(并不是Array实例),因为可以通过索引访问元素,arguments[0]第一个,arguments[1]第二个,因此
function sayHi(name,message){
alert("hello:"+name+","+ message);
}
可改为
function sayHi(name,message){
alert("hello:"+argument[0]+","+ argument[1]);
}
@ argument得length属性
function howManyArgs(){
alert(argument.length);
}
howManyArgs("123",45); //2
howManyArgs(); //0
howManyArgs(12); //1
@可以利用这点
function doAdd(){
if(argument.length==1){
//do
}else if(argument.length==2){
//do
}
}
@有趣的一点
function doAdd(num1,num2){
argument[1]=10;
alert(argument[0]+num2);
}
&每次执行这个doAdd函数都会重写第二个参数,将第二个值修改10.因为argument对象中的值会自动反映到对应的命名参数,所以修改argument[1]自动修改num2,结果值都相同,不过他们的内存空间是独立的,但是值就同步。
&如果只是传入一个参数,那么argument[1]设置的值不会反映到命名参数中,因为argument对象的长度是有传入参数决定,而不是定义函数时候决定
&没有传递的命名参数将自动赋予undefined值,像定义变量但是没初始化一样。
@@严格模式下,上面的赋值会无效,即使设argument[1]=10,num2还是undefined,其次重写argument还会报错
@@没有重载
综上所述,ECMAScript函数没有重载,如果定义多个,则名字只属于最后一个定义的函数
javascript变量松散类型的本质,可以定义任何类型和数据的规则,变量的值及其数据类型可以在脚本的生命周期内改变。
1.基本类型和引用类型
@基本类型指的是简单的数据段,引用类型值指那些可能由多个值构成的对象,
@基本数据类型:Underfined、Null、Boolean、Number、和String,都是按值访问
@引用类型,与其他语言不同,javascript不允许直接访问内存中的位置,不能直接操作对象的内存空间,引用类型的值是按引用访问的
1.1动态的属性(基本类型与引用)
var persion=new Object();
persion.name="Nicholas";
alert(persion.name);//"Nicholas";
var name="Nicholas";
persion.age=27;
alert(persion.age);//undefined ,不报错,但不推荐
1.2复制变量值(基本类型与引用)
@基本类型复制变量值时
var num1=5;
var num2=num1;
num2中的5与num1中的5是完全独立的,该值只是num1中5的一个副本。这两个值参与操作互不影响
复制前
复制后
@引用类型复制变量值时
var obj1=new Object();
var obj2=obj1;
obj1.name="aaa";
alert(obj2.name); //aaa
复制引用变量时候。实际上就是复制一个指针,复制变量结束后,两个变量上将引用同一个对象,改变一个对象则会影响另外一个对象
1.3传递参数
ECMAScript中的所有函数的参数都是按照值传递。就是说函数外部的值复制给函数内部的参数,就和吧一个值复制到另外一个值的变量一样。基本类型复制就像基本类型,引用类型复制就是引用类型
引用传递就是传递该引用,而不是复制多一份变量,值传递就是复制多一份变量。
@基本类型时候
functio addTen(num{
num +=10;
return num;
)
var count =20;
car result =addTen(count);
alert(count);//20,没有变化
alert(result );//30
@引用类型时候
function setNmae(obj){
obj.name="aaa";
}
var persion=new Object();
setName(persion);
alert(persion.name); //aaa
为了证明是复制多一个,而不是直接传递引用,再看下面例子
引用传递就是传递该引用,而不是复制多一份变量,值传递就是复制多一份变量。
function setNmae(obj){
obj.name="aaa";
obj=new Object();
obj.name="bbb";
}
var persion=new Object();
setName(persion);
alert(persion.name); //aaa
用引用的复制原理就能理解出来了,局部对象obj会在函数完毕后自动毁灭。
1.4 检测类型 instanceof
@用typeof操作符确定一个变量是字符串、数值、布尔值、还是undefined的最佳工具,如果是对象或者null。则返回object
@检测基本类型用typeof是得力助手,检测引用类型,很想知道什么类型对象所以用instanceof操作符
alert(person instanceof Object); /变量是Object吗
alert(person instanceof Array); /变量是Array吗
alert(person instanceof RegExp); /变量是RegExp吗
规定,所有应用类型的值都是Object的实力,所以检测一个引用是否Object类型时,instanceof都会返回true,检测基本类型就是返回false,因为基本类型不是对象
@@typeof的兼容性-对正则应用typeof会返回function, 在ie和firefox则object
1.5 执行环境及作用域
@每个执行环境都有一个与之关联的变量对象,全局化解是最外围的一个执行环境,ECMAscript根据宿舍不同,执行环境的对象也不一样,web浏览器全局环境就认为是window对象,该环境被销毁,保存在其中的变量和函数就随之摧毁
@函数也有自己执行环境,执行流进入函数时,函数环境就会被推入环境栈中,函数执行完毕后,栈会将环境弹出,把控制权还给之前的执行环境
@当代码在一个环境执行时候,会创建变量对象的一个作用域链。母的是保证执行环境有权访问所有变量和函数的有序访问
@作用域最前端,始终是当前执行单面所在环境的变量对象,如果环境是函数最开始时候只包含一个变量,即是arguments对象(这个对象在全局环境是不存在的),下一个变量来自包含(外部)环境,而再下一个变量则来自下一个包含环境,这样一直延续到全局执行环境,全局执行环境始终是作用域中的最后一个对象
@标示符解释是沿着作用域一级一级搜索的,搜索过程从作用域最前端开始,然后聚集向后回溯,直接找到(找不到就报错)
var color="blue";
function changeColor(){
color="red";
}
changeColor();
alert(color);
这个例子中,changeColor作用域链包含两个对象:自己的变量arguments和全局变量对象,因为在作用域链向上搜索找到它
var color ="blue";
function changeColor(){
var anotherColor="red";
function swapColors(){
var tempColor= anotherColor;
anotherColor=color;
color= tempColor;
//这里可以访问color、anotherColor和tempColor
}
//这里可以访问color、anotherColor不能访问tempColor
swapColors();
}
这里有三个执行环境:全局环境,changeColor局部环境,swapColors局部环境。
1:全局环境有一个变量color,一个函数changeColor,
2:changeColor的局部环境有一个名为anotherColor变量和函数swapColors,它能向上搜索访问全局环境中的变量函数。
3:swapColors的局部环境有变量tempColor,这变量只能在这个环境环境中访问,因为其他环境向上不能搜索到。而在swapColors都可以访问两个环境中的所有变量,因为它们是是swapColors的符父执行环境
解释:内部环境可以通过作用链范文所有外部环境,外部环境则不能访问内部环境
1.6 延长作用链
在以下语句,作用链将会延长
1.try-catch中的catch语句
2.with语句
兼容问题,不推荐
1.7 没有块级作用域
@if和for
if(true){
var color="blue";
}
alert(color);//true
在其他语言if执行后所定义的变量最自动销毁,但在javascript中变量会添加到当前的执行环境(在这里是全局环境),所以。
for也是一样
@声明变量
1。使用var声明的变量会自动添加到最接近的环境中,函数内部就是函数的局部环境,(在with语句,最最近就是函数环境,with兼容问题和性能不建议使用就不描叙)
2.如果初始化变量没有使用var声明,该变量就会自动添加到全局环境(注意在严格模式中初始化未经声明的变量会导致错误)
下面两个例子(不是严格模式)
1.
function add(num1,num2){
var sum=sum1+sum2;
return sum;
}
var result=add(10,20); //30
alert(num); //会报错,因为函数里面为sum定义了var,那么sum就添加到函数的作用域
2.
function add(num1,num2){
sum=sum1+sum2;
return sum;
}
var result=add(10,20); //30
alert(num); //30,因为sum初始化没有使用var关键字,于是调用完爱到底add()后,会添加到全局环境,所以可以执行不报错
注意:(注意在严格模式中初始化未经声明的变量会导致错误
@查询标识符
1.搜索会在作用链的最前端开始,向上一级一级搜索,知道匹配了该标示符,停止
var color="blue";
function getColor(){
var color="red";
return color;
}
alert(getColor()); //red
注意,如果不使用window.color都无法访问全局color对象
1.8垃圾回收
@标记清除
@引用计数
@性能问题
@管理内存