有没有发现在写代码的时候,往往会遇到一些莫名其妙的错误,然后时间紧急不得不去网上查阅一些代码。虽然要实现的功能解决了,但是看被拷贝的代码好多真心看不懂,以后遇到诸如此类的问题,如果查阅不到这些代码的话还是不会。所以今天给大分享一下内部原理的问题
1.js编译器编译的几条基本原则
a.js预编译:优先解释函数声明,忽略表达式;
b.运行期间:获取变量顺序,由底层向顶层依次查找,直到找到为止。;
c.变量的定义:会被提前到所属代码作用域最前面;
d.function foo(){}
这种声明会被js
编译器解释成var foo;foo = function(){}
这种格式
是不是看了几条规则,不知道我说的什么。没关系,可能是我总结的不好,看下面例子具体了解下
2.自执行函数/闭包
自执行函数,相信大家都接触过。如果不知道,应该只是不知道这个学名而已,在此不给出具体文字定义。
简单解释为:类似(function(){...})()
这种形式的代码就叫做自执行函数,又称闭包他在js编译器解析到时,直接被执行。
一个简单小例子:
(function(){
//...
})()
可以被自执行,写成
function(){
//...
}()
可以被自执行吗?
答:不可以!
这里是因为上面所说规则a :优先解释函数声明,忽略表达式
js预编译时,先解释函数声明,因此function(){...}(
)前面的function(){...}
在‘预编译阶段’已经被解释成变量。js会跳过这段代码,遇到了后面的()
,会试图去执行()
里的内容,显然不科学;
而(function(){...})()
则可以被自执行。因为它加了括号,已经变成了表达式。‘js预编译时’会运行它,并对它求解得到一个返回值。而此处返回值是一个函数,故而遇到最后面的()
便会执行
例子:
a=1;
console.info(a)
function b(){
console.info(a);
var a=10;
console.info(a);
};
b();//1,undefined,10
你是不是预期结果是1,1,10
。
这里正是因为上面的规则c :变量的定义会被提前到所属代码作用域最前面
当js编译器,在执行这个b
函数的时候。会把它‘body’里面的声明变量,提前到最前面进行声明。如:var a=10;
编译器先会在‘body’最前面进行var a
声明(变量提升)。
上面代码等同于下面代码:
a=1;
console.info(a)
function b(){
var a;
console.info(a);
a=10;
console.info(a);
};
b();
声明a的时候还没有值,故而打印undefined;
再看一个例子…
a = 1;
function b(){
a = 10;
return;
function a(){};
};
b();
console.info(a);//1
你是不是预期结果是10
,以为会覆盖全局变量?
这里是因为上面的
规则b :运行期间,获取变量顺序,由底层向顶层依次查找,直到找到为止
规则d :function foo(){}
这种声明会被js
编译器解释成var foo;foo = function(){}
这种格式
上述代码等价于
a = 1;
function b(){
var a;
a = 10;
return;
a = function(){};
}
b();
console.info(a);
3.使用场景
有了上面的理论知识,可以解决曾经有人问我的一个问题:三元表达式后面,如何执行多条语句?其实答案就是在后面写自执行函数。当然,不排除有其它方法,代码如下:
var a = 2 > 1 ?
(function(){ var c = 2, d = 1; return c + d; })()
: (function(){ var c = 2, d = 1; return c - d; })();
console.info(a);//2
这种需求应该很少吧。我宁愿写个if,不过可以实现,呵呵…
author: jyjin
date: 2014.8 [博客搬家]