一、作用域
1) 作用域是指一个变量的作用范围。在JS中,函数、对象也是变量。
2) JS中的作用域分为两种:全局作用域和函数作用域。
1.1 代码块
一个{}叫做一个代码块。
1)代码块后面不需要写分号了。
2)JS中的代码块只具有分组的功能,没有其他用途。
这一个和JAVA不同!!!
1)代码块
<script>
{
var a=10;
a+=1;
console.log(a);
}
{
var b=1;
b+=1;
console.log(b);
}
</script>
2)代码块只用于分组,没有其他用途
<script>
{
var a=10;
a+=1;
console.log(a);
}
console.log(a)
</script>
1.2 JS中的作用域分为两种:全局作用域和函数作用域
二、全局作用域
全局作用域:
1) 直接写在script标签内的代码就在是全局作用域中。
2)全局作用域随着页面的加载而创建,随着页面的关闭而销毁。
一个html页面就是一个全局作用域。
3) 在作用域中,变量声明、函数声明会被提至该作用域的最前面。
4) 全局作用域中默认有一个内置对象,即window对象。
1、在作用域中,变量声明、函数声明会被提前。
在作用域中,变量声明、函数声明会被提至该作用域的最前面。
变量声明提前:
1) 使用var关键字声明的变量会被提至该作用域的最前面。(赋值不会提前)
提前调用返回undefined。
2) 不使用var关键字声明的变量则不会提前。
提前调用报错。
函数声明提前:
1) 使用函数声明创建的函数会被提至该作用域的最前面。
提前调用会执行。
2) 使用其他方式创建的函数不会被提前。
提前调用报错。
>>>>>> 使用var关键字声明的变量会被提前。但是赋值不会提前。提前调用返回undefined。
console.log(s);
var s=12;
>>>>>> 不使用var关键字声明的变量则不会被提前。提前调用报错。
console.log(s);
s=12;
>>>>>> 使用函数声明创建的函数会被提至该作用域的最前面。提前调用会执行。
s();
function s(){
console.log("123")
}
>>>>>> 不使用函数声明创建的函数不会被提至该作用域的最前面。提前调用会报错。
s();
var s=function (){
console.log("123")
}
2、window对象
1) 在全局作用域中默认有一个对象就是window对象。
它代表的是浏览器窗口,我们可以直接使用。
2) 在全局作用域中定义的变量、函数会被作为window的属性、方法来保存。
3) 在函数中不使用var关键字定义的变量会被当做window的属性保存。
>>>>>> 在全局作用域中默认有一个对象,就是window对象。
console.log(window);
>>>>>> 全局变量或函数会被当作window的属性、方法保存。
在全局作用域中定义的变量会被作为window的属性来保存
var s=123;
s2=2121;
console.log(window.s);
console.log(window.s2);
在全局作用域中定义的函数会被作为window的方法来保存
function s(){
alert("123");
}
window.s();
>>>>>> 在函数中不使用var关键字创建的变量会被当做window的属性保存。
案例1
function s(){
num=12;
}
s();
console.log(window.num); //12
console.log(num); //12
案例2
function s(){
c=function ss(){
console.log("12")
}
}
s();
c();
三、函数作用域
1) 函数作用域随着函数的调用而创建,随着函数调用完毕而销毁。
每一个函数就是一个函数作用域。
2) 在作用域中,变量声明、函数声明会被提至该作用域的最前面。
3) 函数操作变量规则:
a) 在函数作用域中可以访问全局作用域中的变量。
但是在全局作用域中访问不到函数作用域中变量。
b) 函数首先会在自身作用域中查找变量。如果没有就会到上一级作用域中查找,直到全局作用域。
在全局作用域中没有找到,就会报错 ReferenceError。
c) 局部变量与成员变量重叠时,采用就近原则。
d) 在函数中想直接使用全局变量,可以使用window对象。
e) 在函数中不使用var关键字创建的变量会被当做window的属性保存。
前提:该函数必须执行。才会成全全局。
f) 定义形参就相当于在函数中声明了变量。
1)在作用域中,变量声明、函数声明会被提前。
>>>>>> 使用var关键字声明的变量会被提前。但是赋值不会提前。提前调用返回undefined。
function s(){
console.log(a);
var a=12;
}
s();
>>>>>> 使用函数声明创建的函数会被提至该作用域的最前面。提前调用会执行。
function s(){
c();
function c(){
console.log("1");
}
}
s();
2)函数操作变量规则
>>>>>> 函数作用域可以访问全局作用域,但是全局作用域不可以访问函数作用域
a)函数作用域可以访问全局作用域变量
var num =12;
function s(){
console.log(num)
}
s();
b) 全局作用域不可以访问函数作用域变量
function s(){
var num =12;
console.log(num)
}
console.log(num);
>>>>>> 函数查找变量, 会从自身作用域到全局作用域依次查找变量。找不到就报错。
a) 案例1
函数s在自己作用域中查找变量num,找到后执行。
var num=12;
function s(){
var num=13;
console.log(num)
}
s();
b) 案例2
函数c在自己作用域中查找num。找不到到上一层作用域查找。直至全局作用域。
在全局作用域查找到num,执行。
var num=12;
function s(){
function c(){
console.log(num);
}
c();
}
s();
c) 案例3
函数c在自己作用域中查找num。找不到到上一层作用域查找。
在函数s中查找到num,执行。
var num=12;
function s(){
var num="222";
function c(){
console.log(num);
}
c();
}
s();
>>>>>> 局部变量与成员变量重叠时,采用就近原则
var num=12;
function s(){
var num=13;
console.log(num)
}
s();
console.log(num); //12
>>>>>> 函数中可以通过window关键字访问全局变量
var num=13;
function s(){
var num =1211;
console.log(window.num);
}
s();
>>>>>> 在函数中不使用var关键字创建的变量会被当做window的属性保存。
案例1
function s(){
num=12;
}
s();
console.log(window.num); //12
console.log(num); //12
案例2
function s(){
c=function ss(){
console.log("12")
}
}
s();
c();
四、变量的访问
4.1 变量提升与函数提升
1、变量提升
通过var定义(声明)的变量, 在定义语句之前就可以访问到
值: undefined
2、 函数提升
通过function声明的函数, 在之前就可以直接调用
值: 函数定义(对象)
3、 提升注意点
函数的提升是整体的提升
变量的提升是声明的提升
函数的提升优于变量的提升
提升是指提升到本层作用域的最顶层
4、注意事项和使用细节
变量的提升不会理会if else 这种条件暗示,会跳出流程,进行提示。
永远不要再流程控制语句的块内部定义函数
案例:
console.log(a)//?
a();//?
var a =3;
function a(){
console.log(10);
}
console.log(a);//?
a = 6;
a();//?
结果为:
function a(){
console.log(10);
}
var a;//再次申明a,并未修改a的值,忽略此处申明
console.log(a)//输出函数本体
a();//函数申明提前,可调用,输出10
a =3;//这里修改值了,a=3,函数已不存在
console.log(a);//输出3
a = 6;//再次修改为6,函数已不存在
a();//a已经为6,没有函数所以没法调用,直接报错
4.2 变量的访问
1、在全局作用域中定义的变量和方法会被都当做window的属性来保存。
2、在函数作用域中不使用var关键字自定的变量会被当做window的属性来保存。
3、函数查找变量,首先会在会在函数作用域中查找变量,如果没有找到,
就会到上一级作用域中查找,直到全局作用域中查找。
在全局作用域中查找就是在window对象中查找变量。
4、查找变量,变量找不到就会报错。
查找属性,属性找不到就会返回undefined。
1)在全局作用域中定义的变量和函数,以及在任意作用域中不使用var关键字定义的变量都会被当做window的属性来保存。
>>>>>> 在全局作用域中定义的变量和函数,会被当做window的属性来保存。
var s="123";
function c(){
console.log("123")
}
console.log(window.s)
console.log(window.c)
>>>>>> 在任意作用域中不使用var关键字定义的变量,会被当做window的属性来保存。
s=12;
function x(){
c=12;
}
x();
console.log(window.s);
console.log(window.c);
2)函数查找变量首先会在自身作用域查找,如果找不到就会到全局作用域中查找,即在window对象中查找。
var cc=12;
function s(){
console.log(cc);
}
s();
3)查找变量,变量找不到就会报错。查找属性,属性找不到就会返回undefined。
//查找变量,变量找不到就会报错
try{
console.log(cc);
}catch(e){
console.log('报错了');
}
//查找属性,属性找不到返回undefined
console.log(window.cc)
4.3 变量的访问应用案例(获取元素的表现样式案例)
>>>>>> 获取元素显示的样式错误案例
直接使用getComputedStyle,在不兼容的浏览器中会报错,所以不能兼容。
原因:查找变量getComputedStyle找不到就会报错。
function getStyle(obj,name){
//首先会在函数作用域中查找变量,没找到就会到全局作用域中查找。
//IE8以上浏览器和其他浏览器有这个属性,找到后执行if。
//IE8以下浏览器没有这个属性。则会报错。
//查找变量,找不到就会报错。 查找属性,找不到返回undefined。
if(getComputedStyle){
//IE8以上版本浏览器和其他浏览器支持
return window.getComputedStyle(obj,null)[name];
}else{
//IE8一下浏览器支持
return obj.currentStyle[name];
}
}
>>>>>> 获取元素的显示样式成功案例
通过对象调用getComputedStyle,在不兼容的浏览器中不会报错,所以可以兼容。
原因:查找属性getComputedStyle,找不到就会返回undefined。
function getStyle(obj,name){
//首先会在函数作用域中查找变量,没找到就会到全局作用域中查找。
//IE8以上浏览器和其他浏览器有这个属性,找到后执行if。
//IE8以下浏览器没有这个属性。则会报错。
//查找变量,找不到就会报错。 查找属性,找不到返回undefined。
if(window.getComputedStyle){
//IE8以上版本浏览器和其他浏览器支持
return window.getComputedStyle(obj,null)[name];
}else{
//IE8一下浏览器支持
return obj.currentStyle[name];
}
}