JavaScript嚴格模式說明及變量函數(shù)的提升
一.嚴格模式的簡單說明
1.函數(shù)調(diào)用的方式和this的丟失
(1)函數(shù)的調(diào)用方法:
- 001 以對象的方法來調(diào)用 this--->對象
- 002 以普通的函數(shù)的方法來調(diào)用 this--->window
- 003 以構(gòu)造函數(shù)的方式來調(diào)用 new Function() this---->指內(nèi)部新創(chuàng)建的對象
- 004 以函數(shù)上下文的方式來調(diào)用(call|apply) this--->綁定的第一個參數(shù) 如果不傳遞參數(shù)那么默認指向window
解決this的丟失問題:
eg:
<script>
//var getId = document.getElementById('demo');//以對象的方法來調(diào)用
/* var getId = document.getElementById;// getId代表是一個函數(shù)
console.log(getId('demo')); */ //報錯 (以普通函數(shù)的方法來調(diào)用)this的丟失問題!
//document.getElementById('demo');
//getId('demo');
//原因:document.getElementById的內(nèi)部實現(xiàn)中使用到了this,內(nèi)部的this始終指向document
//以普通函數(shù)的方式來調(diào)用,內(nèi)部的this指向的是window
//解決問題:
//將this綁定給document
var getId = (function (func){
return function (){
//return func.apply(document,arguments);
return func.call(document,arguments[0]);
}
})(document.getElementById);
console.log(getId('demo'));
var getTagName = (function (func){
return function (){
//return func.apply(document,arguments);
return func.call(document,arguments[0]);
}
})(document.getElementsByTagName);
console.log(getTagName('div')[0]);
</script>
2.嚴格模式的簡單說明
嚴格模式:
js有兩種開發(fā)模式:嚴格模式和非嚴格模式(默認)
在嚴格模式下:會對代碼進行更嚴格的檢查.以前在默認情況下可能不會出錯或者是靜默失敗或者是可以使用的特性,那么會在嚴格模式下會直接報錯.
開啟嚴格模式:
在當前作用域的最頂端加上一個命令字符串:'use strict';
兼容性問題:
- 部分瀏覽器不支持嚴格模式.
- 如果該引擎支持嚴格模式,那么當檢測到'use strict';這個字符串的時候會自動開啟嚴格模式,如果不支持那么就忽略.
嚴格模式的使用注意:
- 01 所有的變量必須使用var聲明
- 02 禁止使用with
- 03 禁止使用八進制
- 04 禁止使用callee | caller
- 05 禁止使用eval和arguments作為標識符
- 06 在if語句中不能聲明函數(shù)
- 07 在函數(shù)的聲明中不能出現(xiàn)同名的參數(shù)
- 08 在對象中不能出現(xiàn)同名的屬性
- 09 在嚴格模式下arguments的表現(xiàn)略微的不同
- 10 不能刪除全局變量
- 11 this的指向被修正
建議:使用嚴格模式來開發(fā).
eg:
<script>
'use strict';
//01 所有的變量必須使用var聲明
/* b = 'testB';
console.log(b);*/
//02 禁止使用with
/* var obj = {
name:'張三'
}
with(obj){
name:'李四'
}
console.log(obj);*/
//03 禁止使用八進制
//八進制說明:如果數(shù)值前面是0,那么默認以八進制的方式來處理
//如果數(shù)字中出現(xiàn)超過8的數(shù)字,那么以十進制的方式來處理
/* var n = 027;
console.log(n);*/
//04 禁止使用callee | caller
//callee 指向自己 用于匿名函數(shù)的遞歸中
//caller 指向調(diào)用者
/* function func01(){
console.log(func01.caller);
}
function func02(){
func01();
}
func02();
console.log((function (n){
if(n == 1){
return 1;
}
return arguments.callee(n-1)+n;
})(11));*/
//05 禁止使用eval和arguments作為標識符(變量|對象|函數(shù)的名稱)
/* var arguments = 'demo';
console.log(arguments);
//06 在if語句中不能聲明函數(shù)
if(true){
function test(){
console.log('test');
}
test();
}*/
//07 在函數(shù)中不能出現(xiàn)同名的參數(shù)
//默認情況下,如果函數(shù)中出現(xiàn)同名的形參,那么后面一個會把前面一個覆蓋
/*function foo(a,b,a){
/!*var a = 1;
var b = 2;
var a = 3;*!/
console.log(a+b+c);//8
}
foo(1,2,3);*/
//08 對象中也不能出現(xiàn)同名的參數(shù) (默認情況下衣形,后面的會覆蓋前面的)
/* var o = {
name:'張三',
name:'李四'
}
console.log(o.name);*/
//09 不能刪除全局變量
//默認情況下刪除失敗岁经,但是不會報錯 (靜默失敗)
/* var obj = '我是測試的魔鏡';
console.log(delete obj);
console.log(obj);*/
//10 argumnets在嚴格模式下和非嚴格模式下表現(xiàn)不一致的
//默認情況下再悼,在函數(shù)內(nèi)部重新設置形參的值鳍置,arguments也會跟著改變迂求,他們是共享的
//嚴格模式下梆惯,他們是相互獨立的
function demoTest(stringTest){
console.log(stringTest);//String
console.log(arguments);//
stringTest = '我是一個字符串';
console.log(stringTest);
console.log(arguments);
}
demoTest('String');
function demoTestObj(obj){
console.log(obj);
console.log(arguments);
obj = {age:23};
console.log(obj);
console.log(arguments);
}
demoTestObj({});
console.log('+++++++++++++++');
//11 修正了this的指向
//默認情況下,指向的是window
//嚴格模式下,指向的是undefined;
var name = 'window的name';
function func01(){
console.log(this);
}
func01();//undefined
var o = {
name:'張三',
showName:function (){
console.log(this);
}
}
o.showName();//張三
var o2 = {
name:'李四'
}
o.showName.call(null);//null
//默認情況下不傳參數(shù)密似,那么this指向window辞居,嚴格模式下指向的是undefined
// 如果傳遞的參數(shù)是null,那么this的值就是null
</script>
3.嚴格模式的書寫格式
- 位置: 當前作用域的最頂端
- 書寫格式:
① 雙引號和單引號無所謂
② 必須全部都是小寫字符
③ 分號可以被省略
④ 必須是10個字符
eg:
<script>
// "use strict";
// "use strict" //省略分號 正確
// use strict; //不加引號 錯誤
// 'use strict'; //單引號 正確
// "use strict"; //錯誤的
// "use strict "; //錯誤的
// "use Strict";
var a = 'testA';
b = 'testB';
</script>
4.嚴格模式的作用域說明
作用域:
js中的作用域分為兩種:全局作用域(例如script作用域內(nèi) )和函數(shù)作用域
作用域: 變量起作用的范圍
塊級作用域:
- js沒有塊級作用域
- 注意:try...catch例外(有塊級作用域)
函數(shù)作用域:
在js中只有函數(shù)可以創(chuàng)建作用域;
詞法作用域:
- 詞法作用域:當代碼寫好之后,它的作用域就已經(jīng)確定了
- 動態(tài)作用域:作用域范圍在程序運行的時候確定;
- js本身是詞法作用域(with + eval + try...catch 除外);
詞法作用域的訪問規(guī)則:
首先先在自己的作用域中查找,如果找到那么就直接使用,如果沒有找到那么就在上一級的作用域中查找,重復這個過程
eg:
<script>
var a = 'testA';
function test01(){
var a = 123;
var b = '456';
console.log(a);
function test02(){
console.log(b);
console.log(a);
}
test02();
}
test01();
console.log(a);
</script>
<script>
function hi(){
console.log('hi');
}
var hello = function hi(){
console.log('hello');
}
hello();//hello
hi();//hi //當賦值之后,就不能再直接使用名稱來調(diào)用
</script>
<script>
var a = 'testA';
function add(n){
//函數(shù)作用域
}
</script>
<script>
for(var i = 0;i<10;i++) {
console.log(i);
}
console.log(i,'------------');
try{
a();
}
catch (e){
console.log(e);
}
console.log(e,'______________');//報錯
</script>
eg2:
<script>
'use strict'; //位置1 作用范圍是全局
function demo1(){
'use strict'; //位置2 demo1
a = 'testA';
}
function demo2(){
'use strict'; //位置3 demo2
b = 'testB';
}
'use strict'; //位置4 無效
demo1();
demo2();
</script>
二.變量和函數(shù)的提升
1. 變量和函數(shù)的提升
01 js預先解析處理 變量和函數(shù)的提升 把變量和函數(shù)提升在作用域頂端
02 具體執(zhí)行
eg:
<script>
console.log(b);//報錯
console.log(a);//undefined
var a = 'testA';//var a; a= 'testA';
console.log(a);//testA;
</script>
<script>
function demo(){
console.log('demo');
}
console.log(typeof demo);//function
demo();//demo
</script>
注意點:
- 01 變量和變量同名的情況, 后面的變量會把前面的同名變量覆蓋
- 02 函數(shù)和函數(shù)名, 后面的函數(shù)會把前面的同名函數(shù)覆蓋
- 03 變量和函數(shù)同名情況 , 前后關(guān)系無所謂
eg:
//01 變量和變量同名的情況
<script>
var num = 10;
function demo1(){
num = 20;
console.log(num);//20
demo2();//30
console.log(num);//30
}
function demo2(){
num = 30;
console.log(num);//
}
demo1();
//02函數(shù)和函數(shù)名
var a = 'testA';
console.log(a);//testA
var a = 'testB';
console.log(a);//testB
//03變量和函數(shù)同名情況
demo1();
function demo1(){
console.log('demo1')
}
demo1();
function demo1(){
console.log('demo2');
}
demo1();
//04變量和函數(shù)同名情況
var str = '我是一個字符串';
str = function (){
console.log('我的同桌是美女')
}
console.log(str);//function()...
</script>
2.變量的提升作用于不同的作用域
eg:
<script>
var num = 10;
function func(){
console.log(num);//10
num = 20;
}
console.log(num);//10
func();//10
console.log(num);//20
/* var num;
function func(){
console.log(num);//undefined
num = 20;
}
num = 10;
console.log(num);//10
func();//10
console.log(num);//20*/
</script>
3.函數(shù)表達式的提升
函數(shù)表達式: 那么在提升的時候僅僅只會把var 變量名提升
eg:
<script>
var demo;
console.log(demo);//undefined
demo();//報錯
demo = function (){
console.log('11111111');
}
</script>