JS的類型
1.基本類型有: String齿椅、Number、Boolean启泣、Undefined涣脚、Null
2.復(fù)雜類型有:Function、RegExp寥茫、Array遣蚀、Object、Date纱耻、Error
3.全局?jǐn)?shù)據(jù)類型:Math
JS閉包
閉包簡(jiǎn)單的說(shuō)就是一個(gè)函數(shù)能訪問(wèn)外部函數(shù)的變量芭梯,這就是閉包,比如說(shuō):
function a(x){
var str=3;
function b(y){
console.log(x+y+str);
}
}
要理解閉包弄喘,首先必須理解Javascript特殊的變量作用域玖喘。變量的作用域無(wú)非就是兩種: 全局變量和局部變量;js中的特殊就在于它們兩個(gè)內(nèi)部的函數(shù)是可以訪問(wèn)外部全局變量的限次,但是外部是無(wú)法訪問(wèn)函數(shù)內(nèi)的局部變量的比如:
//訪問(wèn)外部函數(shù)
var str = 123;
function test(){
console.log(str)
}
test()//結(jié)果為 123
-----------
//訪問(wèn)內(nèi)部函數(shù)
function test2(){
var str2 = 234
}
test2();
console.log(str2)//報(bào)錯(cuò)‘str2 is not defined’
注意 :在訪問(wèn)內(nèi)部函數(shù)的時(shí)候 如果申明變量沒(méi)有使用 var 或者 let(ES6語(yǔ)法) 申明 ,js會(huì)認(rèn)為這是一個(gè)全局變量,所以可以直接訪問(wèn)比如:
function test3(){
str3 = 234
}
test3();
console.log(str3)//結(jié)果為 234
現(xiàn)實(shí)中的各種需求有時(shí)候也不講道理的柴灯,可能你就真的需要去訪問(wèn)閉包里面的函數(shù)來(lái)達(dá)到你想要的效果卖漫,這時(shí)也難不住我們各路大神,比如:
function fn1(){
var numb = 8899;
function fn2(){
console.log(numb)
}
return fn2
}
var fn3 = fn1();
fn3()
上面的函數(shù)運(yùn)行時(shí)fn3()的結(jié)果就是 8899赠群; 運(yùn)用閉包的函數(shù)特點(diǎn)羊始,可以訪問(wèn)父級(jí)函數(shù)的值, 當(dāng)運(yùn)行fn3的時(shí)候相當(dāng)于運(yùn)行了fn1查描,fn2可以直接獲取fn1的局部變量突委,然后fn1直接返回fn2的值,這樣當(dāng)運(yùn)行fn3的時(shí)候就得到了numb的值了
為什么會(huì)這樣呢冬三?原因就在于f1是f2的父函數(shù)匀油,而f2被賦給了一個(gè)全局變量,這導(dǎo)致f2始終在內(nèi)存中勾笆,而f2的存在依賴于f1敌蚜,因此f1也始終在內(nèi)存中,不會(huì)在調(diào)用結(jié)束后窝爪,被垃圾回收機(jī)制(garbage collection)回收;
參考:http://www.jb51.net/article/24101.htm
什么是閉包:
當(dāng)內(nèi)部函數(shù) 在定義它的作用域 的外部 被引用時(shí),就創(chuàng)建了該內(nèi)部函數(shù)的閉包 ,如果內(nèi)部函數(shù)引用了位于外部函數(shù)的變量,當(dāng)外部函數(shù)調(diào)用完畢后,這些變量在內(nèi)存不會(huì)被 釋放,因?yàn)殚]包需要它們.
標(biāo)志性的閉包函數(shù)題:
var str = '全局變量';
var Fn = {
str:'局部變量',
getStr: function(){
return function(){
return this.str
}
}
}
console.log(Fn.getStr()())//結(jié)果為 ’全局變量‘
js函數(shù)繼承
參考鏈接:https://www.zhihu.com/question/41466747/answer/132562725
1.原型繼承
比如:
function a(name){
this.name = name
}
a.prototype.consName = function(){
console.log(this.name)
}
function b(age){
this.age = age
}
b.prototype = new a('hh')
var c = new b(12)
console.log(c.name)//結(jié)果'hh'
console.log(c.age)//結(jié)果為12
c.conName()//結(jié)果為hh
這樣b通過(guò)原型繼承了a弛车,在new b的時(shí)候,c中有個(gè)隱藏的屬性__proto__
指向構(gòu)造函數(shù)的prototype
對(duì)象蒲每,在這里是a對(duì)象實(shí)例纷跛,a對(duì)象里面也有一個(gè)隱藏的屬性__proto__
,指向a構(gòu)造函數(shù)的prototype
對(duì)象,這個(gè)對(duì)象里面又有一個(gè)__proto__
指向Object
的prototype
這種方式有2個(gè)缺點(diǎn)邀杏,第一個(gè)缺點(diǎn)是所有子類共享父類實(shí)例贫奠,如果某一個(gè)子類修改了父類,其他的子類在繼承的時(shí)候,會(huì)造成意想不到的后果叮阅。第二個(gè)缺點(diǎn)是在構(gòu)造子類實(shí)例的時(shí)候刁品,不能給父類傳遞參數(shù)。
2.構(gòu)造函數(shù)繼承
function a(name){
this.name = name
}
function b(age,name){
this.age = age;
a.call(this,name)
}
var c = new b(12,'hha')
c.age//結(jié)果為12
c.name//結(jié)果為hha
注意浩姥,在確定需要將(call())a對(duì)象給b時(shí)挑随, b()的參數(shù)必須要帶上,否則會(huì)顯示為空,或者你訪問(wèn)一個(gè)不存在的參數(shù)會(huì)顯示未定義
采用這種方式繼承是把a(bǔ)中的屬性加到this
上面勒叠,這樣name
相當(dāng)于就是b的屬性兜挨。這種方法的缺點(diǎn)是父類的prototype
中的函數(shù)不能復(fù)用。
js執(zhí)行順序
js中國(guó) 函數(shù)(function)的優(yōu)先級(jí)要高于var變量申明眯分;
例如:
var name = 'hello';
(function(){
if(typeof name === 'undefined'){
console.log('123'+name)
}else{
console.log('234'+name)
}
})()
結(jié)果為:234hello
var name = 'hello';
(function(){
if(typeof name === 'undefined'){
var name = 'world';
console.log('123'+name)
}else{
console.log('234'+name)
}
})()
結(jié)果為 :123world;
注意: 一般函數(shù)內(nèi)部 使用變量會(huì)優(yōu)先使用函數(shù)內(nèi)部(相同于全局變量名稱)的局部變量拌汇,
所以情況一 沒(méi)有局部變量,自執(zhí)行函數(shù)會(huì)直接使用 全局變量 弊决,而全局變量name
為hello
;所以結(jié)果為234hello;
情況二 自執(zhí)行函數(shù)執(zhí)行的時(shí)候 name
值未申明所以 是未定義噪舀,結(jié)果為123world