hoisting机制
javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。
先看一段代码
var v = "hello";
(function(){
 console.log(v);
 var v = "world";
})();
这段代码运行的结果是什么呢?
答案是:undefined
这段代码说明了两个问题,
第一,function作用域里的变量v遮盖了上层作用域变量v。代码做少些变动
var v = "hello";
if(true){
 console.log(v);
 var v = "world";
}  
输出结果为”hello”,说明javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构。
第二,在function作用域内,变量v的声明被提升了。所以最初的代码相当于:
var v = "hello";
(function(){
 var v; //declaration hoisting
 console.log(v);
 v = "world";
})();  
声明、定义与初始化
声明宣称一个名字的存在,定义则为这个名字分配存储空间,而初始化则是为名字分配的存储空间赋初值。
用C++来表述这三个概念
extern int i;//这是声明,表明名字i在某处已经存在了
int i;//这是声明并定义名字i,为i分配存储空间
i = 0;//这是初始化名字i,为其赋初值为0
javascript中则是这样
var v;//声明变量v
v = "hello";//(定义并)初始化变量v
因为javascript为动态语言,其变量并没有固定的类型,其存储空间大小会随初始化与赋值而变化,所以其变量的“定义”就不像传统的静态语言一样了,其定义显得无关紧要。
声明提升
当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明
(function(){
 var a = "1";
 var f = function(){};
 var b = "2";
 var c = "3";
})();  
 
变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:
(function(){
 var a,f,b,c;
 a = "1";
 f = function(){};
 b = "2";
 c = "3";
})();
请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
(function(){
 //var f1,function f2(){}; //hoisting,被隐式提升的声明
 f1(); //ReferenceError: f1 is not defined
 f2();
 var f1 = function(){};
 function f2(){}
})();  
上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。
名字解析顺序
javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
1、语言内置:所有的作用域中都有 this 和 arguments 关键字
2、形式参数:函数的参数在函数作用域中都是有效的
3、函数声明:形如function foo() {}
4、变量声明:形如var bar;
名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:
(function(){
  var foo;
  console.log(typeof foo); //function
  function foo(){}
  foo = "foo";
  console.log(typeof foo); //string
})();  
如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。
以上的名字解析优先级存在例外,比如可以覆盖语言内置的名字arguments。
命名函数表达式
可以像函数声明一样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提升。
f();//TypeError: f is not a function
foo();//ReferenceError: foo is not defined
var f = function foo(){console.log(typeof foo);};
f();//function
foo();//ReferenceError: foo is not defined
命名函数表达式的名字只在该函数的作用域内部有效。
再来看看下面例子:
var myval = "my global var";
(function() {
 console.log(myval); // log "my global var"
})();
以上代码很显然会输出 "my global var",但是如果我们把以上代码按如下方式稍加修改:
var myval = "my global var";
(function() {
 console.log(myval); // log "undefined"
 var myval = "my local var";
})();
执行结果是输出了一个 undefined,出现这个结果的原因就是变量的声明被提升了,以上代码等同如下:
var myval = "my global var";
(function() {
 var myval;
 console.log(myval); // log "undefined"
 myval = "my local var";
})();
被提升的仅仅是变量的声明部分,并没有立即初始化,所以会输出 undefined。
然而这种提升机制,不仅仅表现于在普通的变量,同时也表现在函数上。例如下面这段代码并不能被正确执行:
(function() {
 fun(); // Uncaught TypeError: undefined is not a function
 var fun = function() {
 console.log("Hello!");
 }
})();
因为它等价于:
(function() {
 var fun;
 fun(); // Uncaught TypeError: undefined is not a function
 fun = function() {
 console.log("Hello!");
 }
})();
因为函数的声明同样被提升而没有立即初始化,所以会出错。
当然,这种定义函数的方式称之为“函数表达式”,会有提升机制,如果是如下的这种“函数声明”方式,则完全没有提升机制方面的问题:
(function() {
 fun();
 function fun() {
 console.log("Hello!"); // log "Hello!"
 }
})();
这也是函数声明与函数表达式的主要区别。
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]
 
                        