语法分析,
分析3样东西
第1步: 先分析参数
第2步: 再分析变量声明
第3步: 分析函数声明
一个函数能使用的局部变量,就从上面的3步分析而来
具体步骤:
0: 函数运行前的1瞬间, 生成 Active Object (活动对象),下称AO
1:
1.1 函数声明的参数,形成AO的属性,值全是undefined,
1.2 接收实参,形成AO相应的属性的值
2: 分析变量声明声明声明! 如 var age,
如果AO上还没有age属性,则添加AO属性,值是undefined
如果AO上已经有age属性,则不做任何影响
3: 分析函数声明,如 function foo() {},
则把函数赋给AO.foo属性
注: 如果此前foo属性已存在,则被无情的覆盖了
*/
function t(age) {
alert(age);
}
t(5); // 5
t();// undefined
/*
词法分析过程:
AO {age:undefined}
运行过程:
t(5)--> AO.age=5; alert(AO.age); //5
t() ---> AO.age没得到赋值, 还是undefined
*/
function t2(age) {
var age = 99;
alert(age);
}
t2(5);
/*
分析过程:
0: 形成AO = {}
1:
1.1 分析形参 AO = {age:undefined}
1.2 接收形参 AO = {age:5}
2: 分析var age, 发现AO已有age属性,不做任何影响
执行过程:
AO.age = 99;
alert(age);
*/
function t3(greet) {
var greet = 'hello'; // 试着把这一句变成 var greet;再做分析
alert(greet);
function greet() {
}
alert(greet);
}
t3(null); // hello hello
/*
词法分析过程:
0: AO = {}
1:
1.1 分析参数 AO = {greet:undefined}
1.2 分析参数 AO = {greet:null}
2: 分析greet变量声明,AO已经有greet属性,因此不做任何影响
3: 分析greet函数声明, AO.greet = function() {} , 被覆盖成函数
执行过程:
greet = 'hello';
alert(greet);
alert(greet);
*/
// 再看这道题
function a(b) {
alert(b);
function b(){
alert (b);
}
b();
}
a(1);
/*
分析期:
0: AO = {}
1:
1.1分析参数 AO = {b:undefined}
1.2接收参数 AO = {b:1}
2: 分析var 声明,此函数没有var
3: 分析函数声明, AO = {b: function(){alert(b);}}
执行期:
alert(b); // function
b(); // 由作用域寻找到a函数中的b,即 function,alert()出来
*/
function a(b) {
alert(b);
b = function (){
alert (b);
}
b();
}
a(1);
/*
学员常见答案:
1,1
1, function
1, undefined
function ,function
*/
/*
词法分析过程:
0: AO = {}
1: 分析参数 AO = {b:undefined} --> {b:1}
2: 分析var声明,没有.
3: 分析函数声明?? 没有!
(注: b = function() {} ,是一个赋值过程,在执行期才有用)
执行过程:
alert(b); // 1
b = function() {
alert(b);
}
b(); // function
*/
// 函数声明,与函数表达式
/*
JS被称为披着C外衣的Lisp语言,
lisp是一种强大的函数式语言
函数可以赋值给变量,可以作为参数来传递.
*/
function t1() {
}
t2 = function() {
}
// 这2种方式,效果不同的,
// t1是函数声明, 虽然全局内也得到一个t1变量,值是function
// 而t2 只是一个赋值过程------值是谁? 值是右侧的表达式的返回结果,即函数
// 就是说 function () {} 在js看来,就和 3*2, 6/3 一样,是个表达式,返回一个结果
// 因此,t1 t2 两种方式在词法分析时,有着本质区别
// 前者 在词法分析阶段,就发挥作用
// 而后者,在运行阶段,才发挥作用
// 知道了函数表达式的概念,再看看一个你以前看不懂的东西
(function(window,undefined) {
})(window);
这是jquery的最外层代码
/*
(function(window,undefined){}) // 内层表达式,返回值是函数,包在小括号里,当成表达式来执行\
(function(window,undefined){})(window) // 立即调用
// 而内层函数又没有起名字,称为匿名函数,
// 这种手法,匿名函数,立即执行,不污染全局. 称为 立即执行匿名函数表达式
*/
// 思路: 为什么传window, 而又不会传undefined?
/*
答: 传window是为了速度
function() {
function() {
function () {
function () {
function () {
document.getElementById... // 这个document将会尚作用域层层上找,直到最外层
}
}
}
}
}
jquery就是为了加快内部查找变局变量的速度, 而直接把window以参数形式传进来
这样 window 就在jquery内部的 AO上
不传undefined是为了安全
因为在IE,FF低版本中 , undefined竟然可以重新赋值 ,如 undefined = 3;
声明undefined局部变量(名字是undefined而已), 同时,又不传参,值自然是undefined
防止了外界对undefined的污染
*/
function t1(){ var d function t2(){ d = 5; e=6; }t2();}t1();console.log(d); //d is not definedconsole.log(e); //6console.log(window.d);//undefined
//注意:变量以window.xxx引用,变量不存在,以某个属性不存在报的错 undefined
// 变量以xxx引用的时候,寻找不到,则报的是 xxx is not undefined
// var 仅仅是一个声明变量的操作, d = 5 只是一个赋值操作