Js 预加载

开始 所有的测试,都是chrome浏览器。

  js本身是脚本语言,可以不经过编译直接运行,但是在进入每一个<script>标签,或者js文件的时候,这样的情况下,浏览器会给js一个预编译的过程。

这样就有必要讨论一下预编译了。

  解析的状态是首先引入一个代码段,也就是之前提到的标签或者文件。读入整个代码段,进行解析,解析的方式是遇到变量就声明,

对变量声明为undefined,对函数做标记,这个就是预解析,但是如果声明了同名的函数,使用最后一个。变量都是undefied,只有触发的时候,才会激活。

 

首先举一个例子:

var a;
alert(a);
a = 10;
alert(a);

  预编译的时候,将a设定为undefined。当执行第一个alert的是,会弹出undefined,因为此时a并没有被赋值。

  运行到第二个的时候,弹出10.

 

alert(a);

   直接一句,浏览器会报错。Uncaught ReferenceError: a is not defined。因为a并没有被定义。这是肯定的,

 

但是:

alert(a);
a = 10;

  同样是:Uncaught ReferenceError: a is not defined。这里能证明 如果不是var,那么a=10;虽然js也是定义了一个全局变量,

但是并没有什么用,在预编译阶段,js无法在a=11之前引用它。并不知道a是什么,所以alert(a),并不能识别出来a的存在。证明js

解析是根据字符匹配来解析的,find到var的时候,才会定变量。尽管不是强类型的与语言,但是也无法在预编译的阶段,处理好不带

var 关键字的全局变量。

  

在看函数的例子:

console.log(test);

function test() {
	console.log('haige');
}

  oK,没有问题,会把函数打印出。

 

但是在看这个例子:

console.log(test);

var hg = function test() {
	console.log('haige');
}

  Uncaught ReferenceError: test is not defined。证明,你声明了一个函数,给hg这个变量赋值,但是没什么用,这是什么,是函数表达式。不是函数声明!!!!

 

 修改一下,在看。

console.log(test);

var test = function test() {
	console.log('haige');
}

  undefined 为什么呢?因为test此时是个变量,不是函数。OK,比如这样来看。

 

console.log(typeof test);

var test = function test() {
	console.log('haige');
}

  打印的是undefined。因为预编译的时候,只是声明了一个test变量,证明有,而不知道他是什么。所以无法判断类型。

 

在举一个例子:

var foo = 1;      
function bar() {    
  console.log(foo);  
    if (!foo) {      
        var foo = 10;   
    }      
    console.log(foo);      
}      

bar();

  猜猜看,还是挺有意思的, 第一个console.log()打印的是 undefined。为什么呢?在bar的这个函数作用域中,用var 声明了一个foo的对象,但是,第一次使用时候,由于没有赋值,

所以就出现了undefined的情况,在第二次打印的时候,就已经初始化了,函数执行,是触发式执行方式,从上到下。

 

在举一个更酷的例子

var a = 1;      
function b() {      
  console.log(a);  
    a = 10;      
  console.log(a);  
    return;      
    function a() {}  
}  

b();      
console.log(a);  

  思考一下,这个怎么玩出来,

 第一个打印,a 是一个 function a () {}

 第二个肯定就是10了。

 思考一下为什么,预编译的时候,首先声明了一个全局的a,这个a是一个对象,但是值是undefined,

执行b()函数的时候,给b做预编译。此时,a是function,虽然有return,但是,编译的时候肯定不是看到return就返回了,肯定都编译了。

这样a就变成了一个指向函数的变量。那么执行b()的时候,第一个打印就成function a() {}

执行第二打印的时候,a=10; 所以打印出10.

          变量内的赋值,实在执行的时候完成的,而不是声明的时候。

 

这里在举一个例子证明变量的声明和赋值之间的关系。

a();
var a = function() {};
console.log(a);

  Uncaught TypeError: a is not a function.

在var声明的变量中,在预编译的过程中,都是undefined,当你执行var声明的变量时,才开始触发它所对应的值。

这里的a是变量,虽然给他赋值了函数的指针,但是并没有什么用。因此,在var a = function 之前是无法解析的。

这个浏览器内核,按照变量的声明方式解析,不按照类型解析。

 

 

 之后在思考一下函数之间的预编译问题。

 

function hg(){   
  alert('hg');   
};   
  
hg();   
function hg(){   alert('wj'); }; hg();

 

  思考一下应该如何弹出,结果是两个都是 wj。为什么呢?

很简单,因为函数的解析第二个hg,将第一个覆盖了,而hg是函数名,其实就是一个指针,那么hg将指针的指向,转移到了第二个函数,导致的结果就是,

两次执行,都执行的一个函数,这再次证明了预编译的存在,因为预编译,更改了第一个hg函数的指向。

 

 在看一个例子:

var ys = function(){
	alert('hg');
};   
ys();
ys = function(){ alert('wj'); }; ys();

  ys ()这个函数,其实是在预编译的时候,是个变量,为什么呢?因为var,让编译器知道,他是一个变量,而类型,不是预编译阶段所关心的问题,

在执行第一个ys的时候,OK,根据上下文,ys被赋值为第一个函数。那么就是打印hg,

当执行第二个ys的是,这个时候,ys被赋值为第二个函数,就执行 wj。

 

 还有个例子,很酷的例子。两段代码,做个对比。

(1)

console.log(ys);    //function hg

function ys(){
	console.log('hg');  
}
ys();     // hg

 
var ys = function (){
	console.log('wj');
}   
ys();   //wj

  思考一下,很酷的,在看第二个。

(2)

 

console.log(ys);    //function hg

var ys = function (){
	console.log('wj');
}   
ys();   //wj

function ys(){
	console.log('hg');  
}
ys();    // wj

  这两个例子做了对比,产生了几个很有意思的观点。

首先,如果函数和变量同名,那么,打印出来的就是一个函数,而不变量,这个跟你是否是var定义无关。即使是var定义的变量,依旧,把这个变量,类型变为函数。这个,下一个例子,会看得更清楚。

其次,由于变量的存在,所以是存在运行时动态的赋值的。所以,第一个才会出现ys更改的情况。

但是这里要注意一点,为什么两次的第一个console.log,都打印hg呢?因为var a = function A() {}; 这个在预编译的时候,是不执行的。所以,根本达不到更改ys指针的情况。

 

上面提到的下一个例子:

 

console.log(ys);    //function

function ys(){
	console.log('hg');  
}
console.log(ys);    //function   
var ys = 1;

 

  

 

  打印的是function 和 function 。为什么? 证明:上面提到的,当变量与函数同名的时候,预编译的时候,函数会覆盖变量。

console.log(ys);    //function

function ys(){
	console.log('hg');  
}
var ys = 1;
console.log(ys);    //1

  这种情况了,是因为ys在运行到ys=1是,被重新赋值了。

 

在变量实例化的过程中出现同名,优先级的关系是,声明式函数》函数参数》变量

 

posted on 2015-11-20 01:56  HGonlyWJ  阅读(6807)  评论(0编辑  收藏  举报

W3C中国
阮老师的网络日志
canvas
runoob
迷渡
并发编程网
原生JS例子
前端外刊评论