- 作用域定义:变量(变量作用域又称为上下文)和函数生效(能被访问的区域)
- 全局变量 局部变量
- 作用域的访问顺序
js运行三部曲
- 语法分析
- 预编译
- 解释执行
// 函数声明整体提升 (函数写在哪里,系统都会把函数提升到函数执行之前)
// 变量 声明提升(在同一作用域内变量写在哪里,系统都会把变量提升到改作用域的最前面),如果没有声明变量,直接用了某个变量,则改变量就会提升到当前作用域的父级作用域中,即window下
// 函数声明整体提升
test(1);// 可以执行
function test(a){
console.log(a);
}
// 变量 声明提升 系统会显var b;
console.log(b);//undefined
var b = "123";
相当于 var b; console.log(b); var b = "123";
//-----------隔开 遇到问题 打印的a为什么
// 原因, var a ; a = fn ;
console.log(a);// function () {}
function a(a){
var a = 234;
var a = function () {
}
a();
}
var a = 123;
// --------------------------- 以下为以上产生原因
预编译前奏
- imply global 暗示全局变量:即任何变量,如果变量为未经声明就赋值,此变量就为全局对象所有(全局对象window).
- eg: a = 123;
- eg: var a = b = 123; // b 为全局变脸 window 下的
- 一切声明的全局变量,全都是window的属性
- eg: var a = 123;===> vindow.a = 123;
window.a = 10;
console.log(a);
a = 10; ---> window.a = 10;
var b = 123; ---> window.b = 123;
// window {
// b : 123
// }
function test(){
var c = 123;
console.log(window.c);//undefined
console.log(c);//123
}
console.log(window.c);//undefined
test();
全局对象,即window,window 全局的域;
预编译过程
- 函数预编译
预编译发生在函数执行的前一刻
函数预编译四部曲- 创建AO对象(Activation Object:执行期上下文)
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined(注:如果a没有用var声明,则a为window作用域下,)
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
// 创建AO对象
AO{
//1. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
a : undefined,
b : undefined
///2. 将实参值和形参统一
a : 1,
b : undefined
3.在函数体里面找函数声明,将函数的名称放到AO对象的属性名,值赋值成函数体
a : function a() {},
b : undefined,
d : function d() {}
/ 4. 函数执行
// var a = 123;
a : 123,
b : undefined,
d : function d() {}
}
function fn(a){
console.log(a);// function a() {}
var a = 123;
console.log(a); //123
function a() {} // 预编译已经被提升上去了,所以不看了
console.log(a); // 123
var b = function () {}
console.log(b); // function () {}
function d() {}
}
fn(1);
测试:
function test(a, b) {
document.write(a); // 1
c = 0;
var c;
a = 3;
b = 2;
document.write(b); // 2
function b() {}
function d() {}
document.write(b); // 2
}
test(1);
分析:
AO{
// 1.
a : undefined,
b : undefined,
c : undefined
// 2.
a : 1,
b : undefined,
c : undefined
// 3.
a : 1,
b : function b() {},
c : undefined,
d : function d() {}
// 4. 执行
a : 3,
b : 2,
c : 0,
d : function d() {}
}
function testO(a, b) {
console.log(a);// function a() {}
console.log(b);// undefined
var b = 234;
console.log(b);// 234,
a = 123;
console.log(a);// 123
function a() {}
var a ;
var b = function () {}
console.log(a);// undefined
console.log(b);// function () {}
}
testO(1);
- 全局预编译
全局预编译三部曲- 创建GO对象(Global Object:)
- 找变量为GO的属性,属性值为undefined(如果函数内没有用var定义,则改变量会挂到父级作用域内,即window下)
- 找,函数声明为GO的属性,属性赋值为函数
GO === window
console.log(a);// function a() {}
var a = 123;
function a () {}
console.log(a);// 123
GO{
// 1.
a : function a() {}
// 2.
a : 123
}
AO GO TEST ONE
console.log(window.b)// undefined
// console.log(b)// 报错
function test() {
console.log(a);// undefined
console.log(window.b);//undefined
var a = b = 123;
console.log(a);// 123
console.log(window.a);// undefined
console.log(b)// 123
}
test();
GO{
b : 123;
}
AO{
a : undefined
}
AO GO TEST TWO 先看AO 如果AO没有 再找GO
GO{
// 1.
test : undefined
// 2.
test : function () {}
}
AO{
// 1.
test : undefined
// 2.
test : 1
// 2.
test : function () {}
}
// 先看AO 如果AO没有 再找GO
console.log(test);// function () {}
function test(test) {
console.log(test);// function () {}
var test = 123;
console.log(test);// 123
function test(){}
console.log(test); //123
}
test(1);
var test = 123;
global = 100;
function fu() {
console.log("1---"+global); // undefined
global = 200;
console.log("2---"+global);// 200
var global = 300;
console.log("3---"+global);// 300
}
console.log("4---"+global); // 100
fu();
var global ;
console.log("5---"+global); // 100 GO 先将变量global var global放到GO中,并赋值为 undefined 在赋值为100
// GO{
// // 1.
// fu : function () {},
// global : undefined
// // 2.
// fu : function () {},
// global : 100
// }
//
// AO{
// // 1.
// global : undefined
// // 2.
// global : 200
// // 3.
// global : 300
//
// }
GO{
// 1.
a : undefined,
test : fn,
// 2.
a : 10,
test : fn,
c : 234
}
function test() {
console.log("-- 1" +b); // undefined
if(a){
var b = 100;
}
console.log("-- 2" +b); // undefined
c = 234;
console.log("-- 3" +c);// 234
}
var a ;
test();
AO{
// 1.
b : undefined,
// 2.
b : undefined,
}
a = 10;
console.log("-- 4" +c); // 234
试题
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
console.log(bar());// function foo() {}
AO{
// 1.
foo : undefined
// 2.
foo : function foo() {}
}
document.write(bar());//11
function bar() {
foo = 10;
function foo() {
}
var foo = 11;
return foo;
}
AO{
// 1.
foo : undefined
// 2.
foo : function foo() {}
// 3.
foo : 10
// 4.
foo : 11
}
a = 100;
function demo(e) {
function e() {}
arguments[0] = 2;
document.write("1--" + e + "<br/>");//2 注意arguments的用法
if(a) {
var b = 123;
function c() {}
}
var c;
a = 10;
var a;
document.write("2--" + b+ "<br/>");// undefined
f = 123;
document.write("3--" + c+ "<br/>");//undefined if内提出来
document.write("4--" + a+ "<br/>");//10
}
var a;
demo(1);
document.write("5--" + a+ "<br/>");//100
document.write("6--" + f+ "<br/>");//123
GO{
// 1.
foo : undefined
// 2.
foo : bar
}
//
(window.foo || (window.foo = 'bar'))