作用域
全局作用域
局部作用域(私有作用域)
全局作用域:网页一打开就形成了全局作用域,在函数外面就形成了全局作用域
全局变量:在全局作用域下面定义的变量,在函数外面定义的变量
局部作用域:函数一执行就形成了局部作用域
局部变量:在局部作用域下定义的变量,在函数里面定义的变量,形参也是局部变量
var num = 10; //全局变量
function fun(){
var num = 20; //局部变量
return num;
}
var result = fun();
console.log(result); //20
console.log(num); //10
this关键字
console.log(this); //在全局作用域下this指向window
function fun(){
console.log(this); //普通函数中的this指向window
}
fun();
作用域链:由内往外一层一层查找
var num = 10;
function f1(){
var num = 20;
function f2(){
var num = 30;
function f3(){
var num = 50;
console.log(num);//50
}
f3();
}
f2();
}
f1();
注:会先输出50,由内向外逐一输出
变量提升(预解析)
当网页一打开,浏览器首先会读一遍代码,浏览器会先把带var和function提前声明
1.如果带var浏览器会提前声明,但是只是声明不去赋值,默认结果为undefined
2.变量提升,只提升等号左面的,不会提升等号右面的,即会直接把左面的声明提升到前面去
3.如果是function会声明加定义,就是把整个function提升到代码前面去
练习:
1.
console.log(a); //undefined
var a = 123;
console.log(a); //123
console.log(f); //函数体
function f(){
console.log("函数声明提升");
}
伪代码:
var a;
function f(){
console.log("函数声明提升");
}
console.log(a); //undefined 此时a提升了声明变量但是并未赋值
a = 123;
console.log(a); //123 此时已赋值
console.log(f); //函数体已提升
console.log(a); //undefined
var a = 123;
console.log(a); //123
console.log(f()); //undefined
function f(){
console.log("函数声明提升");
}
f(); //函数声明提升
伪代码:
var a;
console.log(a); //undefined 此时a提升了声明变量但是并未赋值
a = 123;
console.log(a); //123 此时已赋值
console.log(f()); //undefined 就相当于var result = f() //console.log(result);此函数没有返回值所以为undefined
function f(){
console.log("函数声明提升");
}
f();
f(); //3
function f(){
console.log("1");
}
f(); //3
function f(){
console.log("2");
}
f(); //3
function f(){
console.log("3");
}
伪代码:
function f(){
console.log("1");
}
function f(){
console.log("2");
}
function f(){
console.log("3");
}
//最后一个3覆盖了前面的两个函数
f(); //3
f(); //3
f(); //3
console.log(a); //undefined
var a = 123;
console.log(a); //123
function f1(){
console.log(a); //undefined
var a = 456;
console.log(a); //456
}
f1();
console.log(a);
伪代码:
var a;
console.log(a); //undefined
a = 123;
console.log(a); //123
function f1(){
var a;
console.log(a); //undefined
a = 456;
console.log(a); //456
}
f1();
console.log(a); //123
console.log(a); //undefined
var a = 123;
console.log(a); //123
var a = 456;
console.log(a); //456
伪代码:
var a;
console.log(a); //undefined
a = 123;
console.log(a); //123
a = 456;
console.log(a); //456
console.log(a); //函数体
var a = 123;
console.log(a); //123
function a(){}
console.log(a); //123
function a(){}
console.log(a); //123
伪代码:
function a(){}
console.log(a); //函数体
var a = 123;
console.log(a); //123
console.log(a); //123
console.log(a); //123
注:函数和变量同名,函数提升,变量声明不提升
console.log(fn1); //函数体
function fn1() {}
console.log(fn2); //undefined
var fn2 = function() {};
console.log(fn2); //函数体
伪代码:
var fn2;
function fn1() {};
console.log(fn1); //函数体
console.log(fn2); //undefined
fn2 = function(){};
console.log(fn2); //f()匿名函数
console.log(a, b); //undefined undefined
var a = 12;
var b = 13;
sum(); //1
function sum() {
console.log(1);
}
伪代码
var a;
var b;
console.log(a, b); //undefined undefined
a = 12;
b = 13;
function sum() {
console.log(1);
}
sum(); //1
console.log(a); //undefined
var a = 12;
function fn() {
console.log(a); //undefined
var a = 13;
}
fn();
console.log(a); //12
伪代码:
function fn(a) {//此时a为局部的
console.log(a); //undefined
var a = 13; //修改局部的跟全局没关系
}
var a;
console.log(a); //undefined
a = 12;
fn();
console.log(a); //12
console.log(a);// 报错
a = 12;
function fn(){
console.log(a);
var a = 13;
}
fn();
console.log(a)//12
伪代码:
console.log(a);// 前面没有东西,直接报错
a = 12;
var a;
console.log(a); //undefined
a = 12;
function fn(a) {
console.log(a); //12
a = 13;
}
fn(a);
console.log(a); //12
伪代码
function fn(a) { //形参就是变量,变量为局部
console.log(a); //12
a = 13;
}
var a;
console.log(a); //undefined
a = 12;
fn(a);//此时a为实参
console.log(a); //12 拿到了全局的
var foo = 1;
function bar() {
不管判断有没有成立,都要进行变量提升
if (!foo) {
var foo = 10;
}
console.log(foo);
}
bar(); //10
伪代码:
var foo = 1;
function bar() {
var foo;
不管判断有没有成立,都要进行变量提升
if (!foo) {
foo = 10;
}
console.log(foo);
}
bar(); //10
var n = 13;
function fn(n) {
alert(n); //13
var n = 14; //
alert(n); //14
}
fn(n);
console.log(n); //13
伪代码:
function fn(n) {
alert(n); //13
var n = 14; //
alert(n); //14
}
var n;
n = 13;
fn(n);
console.log(n); //13
console.log(a); //undefined
var a = 12;
function fn(a) {
console.log(a); //12
a = 13;
}
fn();
var a;
console.log(a); //13
伪代码:
var a;
console.log(a); //undefined
a = 12;
function fn() {
console.log(a); //12 自身没有找全局,修改也修改了全局的
a = 13;
}
fn();
console.log(a); //13
console.log(a,b,c); //undefined
var a = 10;
b = 20;
c = 30;
function f(a){
console.log(a,b,c); //10,undefined,30
var b = a = c = 100;
console.log(a,b,c); //100,100,100
}
f(10,20);
console.log(a,b,c); //10,20,100
伪代码:
var a;
var b;
var c;
console.log(a,b,c); //undefined undefined undefined
a = 10;
b = 20;
c = 30;
function f(a){
var b;
console.log(a,b,c); //10,undefined,30
b = a = c = 100;
console.log(a,b,c); //100,100,100
}
f(10,20);
console.log(a,b,c); //10,20,100
console.log(num,str);//undefined undefined
var num = 18;
var str = "lily";
function fn2(){
console.log(str,num);//lily undefined
num = 19;
str = "candy";
var num = 14;
console.log(str,num);//candy 14
}
fn2();
console.log(str,num);//candy 18
伪代码:
function fn2(){
var num;
console.log(str,num);//lily undefined
num = 19;
str = "candy";//修改全局的 没有var
num = 14;//局部的 有var
console.log(str,num);//candy 14
}
var num;
var str;
console.log(num,str);//undefined undefined
num = 18;
str = "lily";
fn2();
console.log(str,num);//candy 18