第一:变量声明
在使用javascript时使用变量时首先做的是声明变量,变量声明的关键字是var。
例子:
var i;
var sum;
也可以多个变量声明:
var i,sum;
还可以在声明时赋值。
var i=0;
如果没有给var声明的变量指定初始值,那么在给其初始值之前这变量一直是undefined。
javascript是动态语言在运行期间才会去做数据类型检查,所以不需要给变量指定数据类型,它会在第一次赋值时把数据类型记录下来。
而c和java不一样,它们是静态语言,需要先定义好,数据类型才可以。
例子:
var i=0;
i="len";
先给它赋值一个,然后再给它赋值别的数据类型的值,完全是合法的。
第二:重复声明和遗漏的声明
使用var语句重复声明变量是合法的,这个一条赋值语言没有区别。
这个遗漏声明就不一样了,遗漏声明看你在哪遗漏,这个就要讲究一下了,因为全局变量和局部变量原因。
全局变量就是在javascript代码中的任意位置都有效的变量(前提是这个变量没被声明)。
而这个遗漏声明无论怎么都会变成一个全局变量,但它和你在全局作用域你声明的变量有些不一样,虽然它们
在作用上好像区别不大,但你要知道没声明的变量其实已经变成一个自定义属性,window低下的一个自定义
属性,例如:
V=2;===>window.V=2;
因为在全局作用域下,window可以忽略不写,所以经常会忘记还有window,所以它是可以删除的,在
使用delete运算符时。
例子:
var truevar=1;
delete truevar; //声明了删除不了
fakevar=2;
delete fakevar; //删除了变量
第三:变量作用域
一个变量的作用域是程序源代码中定义这个变量的区域,全局变量拥有全局作用域,在js代码里任何位置都
是有定义的。然而在函数内声明的变量在函数内有定义,它们是局部变量,作用域是局部性的,局部性就是局部使
用,出去这个作用域就会无效,函数的参数也是局部变量,它们只在函数体内有定义。
在函数体内,局部变量比同名的全局变量优先级高,如果函数体内声明一个局部变量或函数参数中带有的变量和全
局变量重名,那么全局变量会被覆盖掉。
例子:
var scope="global";
function part(){
var scope="part";
alert(scope);
}
part(); //弹出的是一个part
alert(scope); //弹出的是一个global
例子:
var scope="global";
function part(){
scope="part";
alert(scope); //弹出part
}
part();
alert(scope); //弹出的是一个part
这个上面那个区别在于在函数里有没有重复声明一个与全局变量同名的变量。从代码的效果很明显,在函数体内没有声明就会
是全局变量,所以重新赋值一次,它的值就会改变。
函数是可以嵌套的,由于每个函数都有自己的作用域,所以会出现几个局部作用域嵌套的情况。
例子:
var scope="1";
function part(){
var scope="2";
function part1(){
var scope="3";
alert(scope); //3
}
alert(scope); //2
}
alert(scope); //1
不做解析,自己想想。
第四:函数作用域和声明提前
在一些语言里花括号内就是一段代码的作用域,而且变量的声明在作用域之外是
不可见的,我们称这为块级作用域。js没有块级作用域,而它有函数作用域,变
量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是由定义的。
function test(){
var i=0;
if(i==0){
console.log(i); //0
}
}
js的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,这个怎么理解呢?
就是如果你在函数体内先使用这个变量,然后再声明这个变量,它就会理解为你已经声明
了这个局部变量了,所以你在使用这个局部变量,无论你在函数体内哪里声明的,在函数
体内哪里使用它,都会解析为你声明了它为局部变量,可以在这个局部使用它,不会改变
全局同名的变量。
例子:
var i=0;
function part(){
alert(i);
var i=1;
}
就是以上的情况,他不会弹出0,但也不会弹出1,因为1的赋值是在使用这个函数之后,所以
它会弹出undefined。
这是不是意味着,变量在声明前就可见、可用了。
而这被称作“声明提前”。就是函数内所有声明的函数都被提前到函数的顶部。
第五:作用域链
简单易懂的说一下吧。当代码在一个环境中执行时,作用域第一个对象始终是当前执行代码所
在环境的变量对象。
如果执行环境是函数,那么将其活动对象作为作用域链第一个对象,第二个对象是包含环境,
下一个是包含环境的包含环境。。。。。一直到找到需要查找的。
在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐
级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
这些需要懂,不是写js代码后出现问题会很吃力。
以下是简单的描述上面的知识:
作用域:
域:空间、范围、区域。。。。
作用:在空间范围可以读写操作
js预解析 //这是声明提前的理解
1)“找一些东西”:var function 参数
a=未定义
所有的变量,在正式运行代码之前,都提前赋了一个值:未定义
fn1=function fn1(){alert(2);}
所以的函数,在正式运行之前,都是整个函数块
2)逐行解读代码
表达式:=、+、-、*、/、%等都是表达式,表达式就是动作,可以改变值
1)如果重名,只有一个存储到仓库,预解析先在到函数块,然后再优先级,从上往下,越下优先级越大;
2)然后逐行读代码
见到表达式就执行 表达式优先
域是至上而下,是单线程的,处理完一个再到下一个,就像引入库;
函数也是一个域,只是一个局部的域;
就会执行预解析的步骤;
如果内部有这个变量,就会优先这个变量,局部变量优先
子级作用域到父级作用域,就是作用域链
解析流程
1)预解析
2)逐行解读代码:
表达式
函数调用:
1)预解析
2)逐行解读代码
传参就是在函数里var 声称一个变量然后赋值给他
想要获取函数里的值:
全局变量
函数里的函数传参