函數(shù)的調(diào)用方式和 this 丟失
- 函數(shù)調(diào)用方式
- 普通函數(shù)方式調(diào)用 this - window
- 對象的方法 this - 對象
- 構(gòu)造函數(shù)方式 this - 內(nèi)部創(chuàng)建的新對象
- 函數(shù)上下文(call|apply) this - 第一個參數(shù)
- this 的指向發(fā)生了改變
函數(shù)的調(diào)用方式發(fā)生了改變
var name = 'window 的屬性';
function demo(){
console.log(this.name);
}
var obj = {
name:"張三",
demo:demo
}
demo();
obj.demo();
var div = document.getElementById('demoId');
console.log(div);
//var div2 = getId('demoId');
//console.log(div2);
//document.getElemenetById 方法內(nèi)部的實現(xiàn)梳凛,在該方法內(nèi)部使用到了 this
//這個 this 默認指向的是document
//getId 在調(diào)用的時候使用普通函數(shù)的方式來進行調(diào)用驾凶, this 指向的是 window
document.getId = document.getElemenetById;
var div3 = document.getId('demoId');
console.log(div3);
//console.log(document.getElemenetById.call(document,''demoId));
//getId('demo');
var getId = (function(){
return function(){
//return document.getElementById.call(document,arguments[0]);
return document.getElemenetById.apply(document,arguments);
}
})();
var div4 = getId('demoId');
console.log(div4);
圖書管理員面向?qū)ο?/h2>
//注意點:在原型對象的方法中訪問該對象的其他方法剩晴,需要使用 this 前綴
function BookListManager(){
this.bookList = null;
}
BookListManager.prototype = {
constructor:BookListManager,
init:function(){
this.bookList = arr || [];
},
getBook:function(name){
for(var i in this.bookList){
if(this.bookList[i].name == name){
return this.bookList[i];
}
}
throw "要查找的對象不存在资溃!"
},
updateBook:function(name,author){
//先找到這個對象
var book = this.getBook(name);
//修改對象
book.author = author;
},
addBook:function(obj){
this.bookList.push(obj);
},
removeBook:function(){
var book = this.getBook(name);
var index = this.bookList.indexOf(book);
if(index == -1){
throw '要刪除的對象不存在'
}
//刪除該對象
this.bookList.splice(index,1);
}
}
var jack = new BookListManager();
var tom = new BookListManager();
jack.init([{name:'古典文學(xué)研究',author:'古典'},{name:'莫言文集',author:'莫言'}]);
jack.addBook({name:'飛鳥集',author:'泰戈爾'});
console.log(jack.getBook('飛鳥集'));
jack.updateBook('飛鳥集','老太太');
jack.removeBook('飛鳥集');
console.log(jack.bookList);
嚴格模式的簡單說明
- js 中有兩種開發(fā)模式,非嚴格模式(默認) + 嚴格模式 ('use strict')
- 嚴格模式會進行更嚴格的代碼檢查
- 以前可以的特性在嚴格模式下可能被禁止使用
- 以前可以使用的代碼方式纲仍,在嚴格模式下會直接報錯
- 開啟嚴格模式
- 字符串命令 'use strict';
- 位置 當前作用域的頂端
- 兼容性問題:
嚴格模式不存在兼容性問題浮创,如果當前的瀏覽器支持嚴格模式差导,那么再掃描到"use strict"命令的時候就會開啟嚴格模式檢查,如果不支持嚴格模式那么就直接忽略
- 使用建議
建議在寫代碼的時候全部開啟嚴格模式
嚴格模式使用注意
- 在嚴格模式下帜消,所有的變量都必須使用 var 聲明
- 在嚴格模式下棠枉,禁止使用八進制
- 在嚴格模式下,禁止使用 with
- 在嚴格模式下泡挺,不能刪除全局的變量
- 在嚴格模式下辈讶,不能在 if 語句中聲明函數(shù)
- 在嚴格模式下,函數(shù)的形參不能出現(xiàn)同名的情況
- 在嚴格模式下娄猫,不能使用 callee|caller
- 在嚴格模式下贱除,不能使用 eval 和 arguments 作為標識符(變量和函數(shù)名稱)
- 在嚴格模式下,修正了 this 的指向
- 在嚴格模式下媳溺,arguments 的表現(xiàn)不一致
- 在嚴格模式下月幌,對象中不能出現(xiàn)同名的屬性
"use strict";
//01 在嚴格模式下,所有的變量都必須使用var聲明
// 在默認情況下悬蔽,如果不適用var聲明變量扯躺,那么該變量默認會成為window的屬性(全局變量)
// var a = 10;
// b = 20;
// console.log(b);
//02 在嚴格模式下,禁止使用八進制
// var num = 022; //數(shù)值以0開頭,以八進制的方式來處理
// var num = 0x22;
// console.log(num);
//03 在嚴格模式下录语,禁止使用使用with
// var obj = {name:"張三",age:20};
// with (obj)
// {
// name = "李四";
// age = 99
// }
// console.log(obj);
//04 在嚴格模式下, 不能刪除全局的變量
// 在默認情況下倍啥,可以刪除全局變量(不能刪除成功),靜默失敗
// var str = "string";
// console.log(delete str);
// console.log(str);
//05 在嚴格模式下澎埠,不能在if語句中聲明函數(shù)
// if (true)
// {
// function demo() {
// console.log("demo");
// }
//
// demo();
// }
//06 在嚴格模式下虽缕,函數(shù)的形參不能出現(xiàn)同名的情況
// function test(a,b,a) {
//// var a = 1;
//// var b = 2;
//// var a = 3;
// console.log(a + b + a); //6 ? 8 ? 4 后面的會把前面的覆蓋
// }
//
// test(1,2,3);
//07 在嚴格模式下,不能使用arguments.callee|caller
//caller 指向的函數(shù)的調(diào)用者 注意點:window調(diào)用該函數(shù)蒲稳,指向的是null
//arguments.callee 常用在遞歸調(diào)用中彼宠,指向的是函數(shù)自己
// function f1() {
// f2();
// }
// function f2() {
// console.log(f2.caller);
// }
// f1();
// f2();
// console.log((function (n) {
// if (n == 1) {
// return 1;
// }
//
// return arguments.callee(n - 1) + n;
//})(11));
//08 在嚴格模式下, 不能使用eval和arguments作為標識符(變量和函數(shù)的名稱)
// var eval = "測試字符串";
// console.log(eval);
// var arguments ="....";
// console.log(arguments);
//09 在嚴格模式下,修正了this的指向
// 默認情況下弟塞,this指向的是window,嚴格模式指向的undefined
// function func() {
// console.log(this);
// }
//
// func();
// var o = {};
// func.call(null); //嚴格模式下凭峡,指向的是null
//10 在嚴格模式下,arguments的表現(xiàn)不一致
//在默認情況下决记,如果函數(shù)內(nèi)部形參被重新設(shè)置摧冀,那么arguments也會跟著改變
//在嚴格模式情況下,如果函數(shù)內(nèi)部形參被重新設(shè)置系宫,那么arguments不會被改變索昂,他們是相互獨立的
//值類型的數(shù)據(jù)作為函數(shù)的參數(shù)
function demo(str) {
console.log(str);
console.log(arguments[0]);
//重新設(shè)置形參的值
str = "hahahaha";
console.log(str);
console.log(arguments[0]);
}
demo("123456");
//引用類型的數(shù)據(jù)作為函數(shù)參數(shù)
function demo(obj) {
console.log(obj);
console.log(arguments[0]);
//重新設(shè)置形參的值
obj = {age:20};
console.log(obj);
console.log(arguments[0]);
}
demo({name:"張三"});
嚴格模式的書寫格式
//"use strict";
//"use strict" 正確
//'use strict'; 正確
//'use strict' 正確
//use strict; 錯誤
//"use Strict"; 錯誤
//"use strict"; 錯誤
//"use strict "; 錯誤
//" use strict"; 錯誤
嚴格模式的作用范圍
- 位置:當前作用域的最上面
- js 中的作用域:
- script 標簽 全局作用域
- 函數(shù)內(nèi)部 局部作用域
// "use strict"; //位置01 對整個作用域中的代碼都有用
function demo01() {
// "use strict"; //位置02 僅僅對當前的函數(shù)有用,函數(shù)后面的代碼不受影響
a = 10;
console.log(a);
}
function demo02() {
// "use strict"; //位置03 僅僅對當前的函數(shù)有用
b = 20;
console.log(b);
}
demo01();
demo02();
作用域說明
- 作用域
概念:變量或者是函數(shù)起作用的范圍
- js 的作用域
- js 本身沒有塊級作用域(try-catch 除外)
- js 中只有函數(shù)可以創(chuàng)建作用域
- js 本身是此法作用域 (with|eval 除外)
- 詞法作用域:
當代碼寫好之后扩借,某個變量的作用域就已經(jīng)確定了
- 動態(tài)作用域:
變量的作用域在代碼運行之前是不確定的椒惨,只有在代碼執(zhí)行的時候才能根據(jù)當前的上下文來確定
- 詞法作用域的訪問規(guī)則:
- 單向性的(單向鏡),內(nèi)部的作用域可以訪問外層的作用域空間潮罪,反過來卻不行
- 在訪問變量的時候康谆,先在當前作用于中查找,如果找不到那么就在上一級作用域中查找嫉到,重復(fù)這個過程
- 在分析輸出的時候沃暗,需要考慮到變量和函數(shù)聲明的提升
var a = "test-A";
function f1() {
var b = "test-B";
}
function f2() {
var c = "test-C";
}
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i,"_____"); //? 10
try
{
//可能出錯的代碼
a();
}catch (error){
//如果出錯了,那么就執(zhí)行此處的代碼
console.log(error);
}
// console.log(error);
var demo = "測試的字符串01";
function f1() {
var demo = "demo";
var test = 10;
f2();
}
function f2() {
console.log(demo);
console.log(test);
}
// f2(); //測試的字符串
f1(); //demo
變量和函數(shù)的提升
- js 代碼的執(zhí)行
編譯語言
解釋語言(js)
- 預(yù)先解析階段
變量和函數(shù)聲明的提升
- 具體的執(zhí)行代碼
- js 變量和函數(shù)聲明提升的注意點
- 變量和變量同名 后面的變量會把前面的變量覆蓋
- 函數(shù)和函數(shù)同名 覆蓋
- 變量和函數(shù)同名 函數(shù)聲明會正常的提升何恶,而變量的聲明可以認為被忽略了
只會提升到當前作用域的最頂端
console.log("_____");
console.log(a); //und
var a = "test-A";
console.log(a); //Test-A
var a = "demo-A";
console.log(a); //demo-A
//模擬變量聲明的提升
// var a;
// console.log("_____");
// console.log(a); //und
// a = "test-A";
// console.log(a); //Test-A
// a = "demo-A";
// console.log(a); //demo-A
</script>
<script>
f1(); //Demo
function f1() {
console.log("Test");
}
f1(); //Demo
function f1() {
console.log("Demo");
}
f1(); //Demo
//模擬提升
// function f1() {
// console.log("Demo");
// }
// f1(); //Demo
// f1(); //Demo
// f1();
</script>
<!--<script>-->
<!--console.log(a); //函數(shù)-->
<!--var a = "test-A";-->
<!--function a() {-->
<!--console.log("demo-A");-->
<!--}-->
<!--console.log(a); //函數(shù)-->
<!--//模擬-->
<!--var a;-->
<!--function a() {-->
<!--console.log("demo-A");-->
<!--}-->
<!---->
<!--console.log(a); //函數(shù)-->
<!--a = "test-A";-->
<!--console.log(a); //test-A-->
<!--</script>-->
<script>
console.log(a);
var a = "test-A";
function a() {
console.log("demo-A");
}
// 不管函數(shù)在前面還是變量在前面孽锥,打印出來的結(jié)果都是函數(shù)
</script>
思考:
<script>
var demoA ="10";
function foo() {
console.log(demoA); //10 undefined(正確)
var demoA = "20";
console.log(demoA); //20
}
function func() {
console.log(demoA); //10
demoA = "30";
console.log(demoA); //30
}
foo();
func();
console.log(demoA); //30
變量提升是分作用域的
- 在代碼執(zhí)行之前,會把所有的變量和函數(shù)生命進行提升
- 在提升的時候细层,變量和函數(shù)聲明的提升是分作用域的惜辑,只能提升到當前作用域的頂端
- 內(nèi)層作用域中的變量聲明并不會覆蓋外層作用域中的同名變量
console.log(demo);
var a = "第一個a";
function demo() {
console.log(a); //? undefined
a = "張三";
console.log(a); //張三
var a = "哈哈哈";
console.log(a); //哈哈哈
}
console.log(a);
demo();
console.log(a); //第一個a(正確) ? 張三 ?哈哈哈
</script>
<script>
var b = 10;
function test() {
console.log(b);
var b = 20;
}
console.log(b); //10
test(); //und
console.log(b);
</script>
函數(shù)表達式的提升
- 函數(shù)表達式提升疫赎,在提升的時候僅僅只會把聲明部分(var func02)提升到當前作用域的頂端
<script>
console.log(func01);;
function func01() {
console.log("func01");
}
</script>
<script>
// var func02;
console.log(func02);;
var func02 = function () {
console.log("func02");
}
</script>
筆試題練習(xí)
<script>
function foo() {
var num = 123;
console.log(num); //123
}
foo();
//console.log(num); //報錯
</script>
<script>
var scope = "global";
foo();
function foo() {
console.log(scope); //盛撑?global
scope = "local";
console.log(scope); //?local
}
console.log(scope); //local
</script>
in:檢查對象中是否存在指定的屬性
<!--<script>-->
<!--function f1(){-->
<!--var a;-->
<!--if("a" in window){-->
<!--a = 10;-->
<!--}-->
<!--console.log(a); //? 10 虚缎? undefined 讶隐?報錯-->
<!--}-->
<!--f1();-->
<!--</script>-->
<!--<script>-->
<!--if("a" in window){-->
<!--var a = 10;-->
<!--}-->
<!--console.log(a); //? 10 -->
<!--</script>-->
<!--<script>-->
<!--if(!"a" in window){-->
<!--var a = 10;-->
<!--}-->
<!--console.log(a); //?-->
<!--</script>-->
<script>
if("a" in window){
a = 10;
}
console.log(a); //? 報錯
</script>
<script>
var foo = 1;
function bar() {
var foo;
if(!foo)
{
foo = 10;
}
console.log(foo); //?
}
bar();
// undefined == null; 相等
// undefined == false; 不相等
// !undefined
console.log(undefined === null); //true
console.log(!undefined == true);
</script>
function Foo() {
getName = function(){
console.log("1");
};
return this;
}
Foo.getName = function() {
console.log("2");};
Foo.prototype.getName = function(){
console.log("3");};
var getName = function() {
console.log("4");
};
function getName(){
console.log("5");
}
Foo.getName(); // ? 2
getName(); // ? 4
Foo().getName(); // ? (1) ? 3 ? 2 ? 4
getName(); // ? (1)
new Foo.getName(); // ? 2
new Foo().getName(); // ? 3
new new Foo().getName(); // ? 3
作用域鏈
- 有多少個作用域 (函數(shù)的個數(shù) + 1)
- 相同作用域可以相互訪問
- 作用域鏈:
在 js 中函數(shù)可以創(chuàng)建作用域楷扬,在函數(shù)內(nèi)部又可以聲明函數(shù)嘿般,在函數(shù)的函數(shù)內(nèi)部又可以聲明函數(shù),每個函數(shù)都會創(chuàng)建一個作用域,這樣就會形成一個作用域鏈
- 在訪問變量的時候,總是先在自己的作用域中查找
- 如果沒有那么就向上一級作用域查找,如果找到那么就直接使用受葛,如果沒有找到那么就繼續(xù)重復(fù)這個過程
- 直到最外層的全局作用域,如果還沒有找到那么就報錯
var a = "a";
//f1--->全局作用域
function f1() {
var b = "b";
var a = "f1-a"
//f2-->f1--->全局作用域
function f2() {
var c = "c";
var b = "f2--b";
//f3-->f2-->f1--->全局作用域
function f3() {
var d = "d";
//f4-->f3-->f2-->f1--->全局作用域
function f4() {
console.log(a, b, c, d,e);
}
f4();
}
f3();
}
f2();
}
f1();
作用域鏈繪圖
首先先找出全局變量(包含函數(shù)) a f1 f2 f3
畫出他們的圖形偎谁,并且連線(有箭頭)总滩,箭頭的方向表示的是是否可以訪問(同一級作用域可以互相訪問)
-
以上畫出0級作用域鏈 var a = "test-a";
function f1() {
var b = "test-b";
function f4() {
function f5() {
var c = "test-c";
var d = "test-d"
}
}
}
function f2() {
var e = "test-e";
//注意點:在原型對象的方法中訪問該對象的其他方法剩晴,需要使用 this 前綴
function BookListManager(){
this.bookList = null;
}
BookListManager.prototype = {
constructor:BookListManager,
init:function(){
this.bookList = arr || [];
},
getBook:function(name){
for(var i in this.bookList){
if(this.bookList[i].name == name){
return this.bookList[i];
}
}
throw "要查找的對象不存在资溃!"
},
updateBook:function(name,author){
//先找到這個對象
var book = this.getBook(name);
//修改對象
book.author = author;
},
addBook:function(obj){
this.bookList.push(obj);
},
removeBook:function(){
var book = this.getBook(name);
var index = this.bookList.indexOf(book);
if(index == -1){
throw '要刪除的對象不存在'
}
//刪除該對象
this.bookList.splice(index,1);
}
}
var jack = new BookListManager();
var tom = new BookListManager();
jack.init([{name:'古典文學(xué)研究',author:'古典'},{name:'莫言文集',author:'莫言'}]);
jack.addBook({name:'飛鳥集',author:'泰戈爾'});
console.log(jack.getBook('飛鳥集'));
jack.updateBook('飛鳥集','老太太');
jack.removeBook('飛鳥集');
console.log(jack.bookList);
嚴格模式不存在兼容性問題浮创,如果當前的瀏覽器支持嚴格模式差导,那么再掃描到"use strict"命令的時候就會開啟嚴格模式檢查,如果不支持嚴格模式那么就直接忽略
建議在寫代碼的時候全部開啟嚴格模式
"use strict";
//01 在嚴格模式下,所有的變量都必須使用var聲明
// 在默認情況下悬蔽,如果不適用var聲明變量扯躺,那么該變量默認會成為window的屬性(全局變量)
// var a = 10;
// b = 20;
// console.log(b);
//02 在嚴格模式下,禁止使用八進制
// var num = 022; //數(shù)值以0開頭,以八進制的方式來處理
// var num = 0x22;
// console.log(num);
//03 在嚴格模式下录语,禁止使用使用with
// var obj = {name:"張三",age:20};
// with (obj)
// {
// name = "李四";
// age = 99
// }
// console.log(obj);
//04 在嚴格模式下, 不能刪除全局的變量
// 在默認情況下倍啥,可以刪除全局變量(不能刪除成功),靜默失敗
// var str = "string";
// console.log(delete str);
// console.log(str);
//05 在嚴格模式下澎埠,不能在if語句中聲明函數(shù)
// if (true)
// {
// function demo() {
// console.log("demo");
// }
//
// demo();
// }
//06 在嚴格模式下虽缕,函數(shù)的形參不能出現(xiàn)同名的情況
// function test(a,b,a) {
//// var a = 1;
//// var b = 2;
//// var a = 3;
// console.log(a + b + a); //6 ? 8 ? 4 后面的會把前面的覆蓋
// }
//
// test(1,2,3);
//07 在嚴格模式下,不能使用arguments.callee|caller
//caller 指向的函數(shù)的調(diào)用者 注意點:window調(diào)用該函數(shù)蒲稳,指向的是null
//arguments.callee 常用在遞歸調(diào)用中彼宠,指向的是函數(shù)自己
// function f1() {
// f2();
// }
// function f2() {
// console.log(f2.caller);
// }
// f1();
// f2();
// console.log((function (n) {
// if (n == 1) {
// return 1;
// }
//
// return arguments.callee(n - 1) + n;
//})(11));
//08 在嚴格模式下, 不能使用eval和arguments作為標識符(變量和函數(shù)的名稱)
// var eval = "測試字符串";
// console.log(eval);
// var arguments ="....";
// console.log(arguments);
//09 在嚴格模式下,修正了this的指向
// 默認情況下弟塞,this指向的是window,嚴格模式指向的undefined
// function func() {
// console.log(this);
// }
//
// func();
// var o = {};
// func.call(null); //嚴格模式下凭峡,指向的是null
//10 在嚴格模式下,arguments的表現(xiàn)不一致
//在默認情況下决记,如果函數(shù)內(nèi)部形參被重新設(shè)置摧冀,那么arguments也會跟著改變
//在嚴格模式情況下,如果函數(shù)內(nèi)部形參被重新設(shè)置系宫,那么arguments不會被改變索昂,他們是相互獨立的
//值類型的數(shù)據(jù)作為函數(shù)的參數(shù)
function demo(str) {
console.log(str);
console.log(arguments[0]);
//重新設(shè)置形參的值
str = "hahahaha";
console.log(str);
console.log(arguments[0]);
}
demo("123456");
//引用類型的數(shù)據(jù)作為函數(shù)參數(shù)
function demo(obj) {
console.log(obj);
console.log(arguments[0]);
//重新設(shè)置形參的值
obj = {age:20};
console.log(obj);
console.log(arguments[0]);
}
demo({name:"張三"});
//"use strict";
//"use strict" 正確
//'use strict'; 正確
//'use strict' 正確
//use strict; 錯誤
//"use Strict"; 錯誤
//"use strict"; 錯誤
//"use strict "; 錯誤
//" use strict"; 錯誤
// "use strict"; //位置01 對整個作用域中的代碼都有用
function demo01() {
// "use strict"; //位置02 僅僅對當前的函數(shù)有用,函數(shù)后面的代碼不受影響
a = 10;
console.log(a);
}
function demo02() {
// "use strict"; //位置03 僅僅對當前的函數(shù)有用
b = 20;
console.log(b);
}
demo01();
demo02();
概念:變量或者是函數(shù)起作用的范圍
當代碼寫好之后扩借,某個變量的作用域就已經(jīng)確定了
變量的作用域在代碼運行之前是不確定的椒惨,只有在代碼執(zhí)行的時候才能根據(jù)當前的上下文來確定
var a = "test-A";
function f1() {
var b = "test-B";
}
function f2() {
var c = "test-C";
}
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i,"_____"); //? 10
try
{
//可能出錯的代碼
a();
}catch (error){
//如果出錯了,那么就執(zhí)行此處的代碼
console.log(error);
}
// console.log(error);
var demo = "測試的字符串01";
function f1() {
var demo = "demo";
var test = 10;
f2();
}
function f2() {
console.log(demo);
console.log(test);
}
// f2(); //測試的字符串
f1(); //demo
編譯語言
解釋語言(js)
變量和函數(shù)聲明的提升
只會提升到當前作用域的最頂端
console.log("_____");
console.log(a); //und
var a = "test-A";
console.log(a); //Test-A
var a = "demo-A";
console.log(a); //demo-A
//模擬變量聲明的提升
// var a;
// console.log("_____");
// console.log(a); //und
// a = "test-A";
// console.log(a); //Test-A
// a = "demo-A";
// console.log(a); //demo-A
</script>
<script>
f1(); //Demo
function f1() {
console.log("Test");
}
f1(); //Demo
function f1() {
console.log("Demo");
}
f1(); //Demo
//模擬提升
// function f1() {
// console.log("Demo");
// }
// f1(); //Demo
// f1(); //Demo
// f1();
</script>
<!--<script>-->
<!--console.log(a); //函數(shù)-->
<!--var a = "test-A";-->
<!--function a() {-->
<!--console.log("demo-A");-->
<!--}-->
<!--console.log(a); //函數(shù)-->
<!--//模擬-->
<!--var a;-->
<!--function a() {-->
<!--console.log("demo-A");-->
<!--}-->
<!---->
<!--console.log(a); //函數(shù)-->
<!--a = "test-A";-->
<!--console.log(a); //test-A-->
<!--</script>-->
<script>
console.log(a);
var a = "test-A";
function a() {
console.log("demo-A");
}
// 不管函數(shù)在前面還是變量在前面孽锥,打印出來的結(jié)果都是函數(shù)
</script>
思考:
<script>
var demoA ="10";
function foo() {
console.log(demoA); //10 undefined(正確)
var demoA = "20";
console.log(demoA); //20
}
function func() {
console.log(demoA); //10
demoA = "30";
console.log(demoA); //30
}
foo();
func();
console.log(demoA); //30
console.log(demo);
var a = "第一個a";
function demo() {
console.log(a); //? undefined
a = "張三";
console.log(a); //張三
var a = "哈哈哈";
console.log(a); //哈哈哈
}
console.log(a);
demo();
console.log(a); //第一個a(正確) ? 張三 ?哈哈哈
</script>
<script>
var b = 10;
function test() {
console.log(b);
var b = 20;
}
console.log(b); //10
test(); //und
console.log(b);
</script>
<script>
console.log(func01);;
function func01() {
console.log("func01");
}
</script>
<script>
// var func02;
console.log(func02);;
var func02 = function () {
console.log("func02");
}
</script>
<script>
function foo() {
var num = 123;
console.log(num); //123
}
foo();
//console.log(num); //報錯
</script>
<script>
var scope = "global";
foo();
function foo() {
console.log(scope); //盛撑?global
scope = "local";
console.log(scope); //?local
}
console.log(scope); //local
</script>
in:檢查對象中是否存在指定的屬性
<!--<script>-->
<!--function f1(){-->
<!--var a;-->
<!--if("a" in window){-->
<!--a = 10;-->
<!--}-->
<!--console.log(a); //? 10 虚缎? undefined 讶隐?報錯-->
<!--}-->
<!--f1();-->
<!--</script>-->
<!--<script>-->
<!--if("a" in window){-->
<!--var a = 10;-->
<!--}-->
<!--console.log(a); //? 10 -->
<!--</script>-->
<!--<script>-->
<!--if(!"a" in window){-->
<!--var a = 10;-->
<!--}-->
<!--console.log(a); //?-->
<!--</script>-->
<script>
if("a" in window){
a = 10;
}
console.log(a); //? 報錯
</script>
<script>
var foo = 1;
function bar() {
var foo;
if(!foo)
{
foo = 10;
}
console.log(foo); //?
}
bar();
// undefined == null; 相等
// undefined == false; 不相等
// !undefined
console.log(undefined === null); //true
console.log(!undefined == true);
</script>
function Foo() {
getName = function(){
console.log("1");
};
return this;
}
Foo.getName = function() {
console.log("2");};
Foo.prototype.getName = function(){
console.log("3");};
var getName = function() {
console.log("4");
};
function getName(){
console.log("5");
}
Foo.getName(); // ? 2
getName(); // ? 4
Foo().getName(); // ? (1) ? 3 ? 2 ? 4
getName(); // ? (1)
new Foo.getName(); // ? 2
new Foo().getName(); // ? 3
new new Foo().getName(); // ? 3
在 js 中函數(shù)可以創(chuàng)建作用域楷扬,在函數(shù)內(nèi)部又可以聲明函數(shù)嘿般,在函數(shù)的函數(shù)內(nèi)部又可以聲明函數(shù),每個函數(shù)都會創(chuàng)建一個作用域,這樣就會形成一個作用域鏈
var a = "a";
//f1--->全局作用域
function f1() {
var b = "b";
var a = "f1-a"
//f2-->f1--->全局作用域
function f2() {
var c = "c";
var b = "f2--b";
//f3-->f2-->f1--->全局作用域
function f3() {
var d = "d";
//f4-->f3-->f2-->f1--->全局作用域
function f4() {
console.log(a, b, c, d,e);
}
f4();
}
f3();
}
f2();
}
f1();
首先先找出全局變量(包含函數(shù)) a f1 f2 f3
畫出他們的圖形偎谁,并且連線(有箭頭)总滩,箭頭的方向表示的是是否可以訪問(同一級作用域可以互相訪問)
以上畫出0級作用域鏈 var a = "test-a";
function f1() {
var b = "test-b";
function f4() {
function f5() {
var c = "test-c";
var d = "test-d"
}
}
}
function f2() {
var e = "test-e";
// f4();
}
function f3() {
}
f2();