摘要:調(diào)用函數(shù)時(shí),被綁定到全局對象。如果使用構(gòu)造器調(diào)用有前綴,且返回不是一個(gè)對象,則返回該新對象。閉包會(huì)導(dǎo)致原有作用域鏈不釋放,造成內(nèi)存泄漏。當(dāng)采用構(gòu)造器調(diào)用模式,函數(shù)執(zhí)行的方式會(huì)被修改。
內(nèi)容
ECMAScript核心語法結(jié)構(gòu):一、語法 1.類型、值和變量
1.語法
2.對象
3.函數(shù)
4.繼承
5.數(shù)組
6.正則表達(dá)式
7.方法
8.附錄A-毒瘤
9.附錄B-糟粕
1) 類型:區(qū)分?jǐn)?shù)據(jù)類型
在JS中使用var關(guān)鍵詞聲明變量,變量的類型會(huì)根據(jù)其所賦值來決定(動(dòng)態(tài)類型)。 JS中數(shù)據(jù)類型分為原始數(shù)據(jù)類型(5種)和引用數(shù)據(jù)類型(Object類型)。
原始數(shù)據(jù)類型(5):Number、String、Boolean、Undefined、Null。需要注意的是JS中字符串屬于原始數(shù)據(jù)類型。
typeof返回值(6):number、string、boolean、undefined、object、function 。null返回object
instanceof:解決引用類型判斷問題 詳解
3) 變量
變量:局部變量和全局變量
變量提升:
函數(shù)及變量的聲明都將被提升到函數(shù)的最頂部。
變量可以在使用后聲明,也就是變量可以先使用再聲明。
1) 條件語句
if:
switch:
2)循環(huán)語句
while
for
do
3)強(qiáng)制跳轉(zhuǎn)語句
continue:跳出單次循環(huán)
break:跳出單層循環(huán)
return:函數(shù)返回語句,但是返回的同時(shí)也將函數(shù)停止
throw:創(chuàng)建或拋出異常
4)應(yīng)用
1.label應(yīng)用-跳出多層循環(huán)
var obj={ "last-name":"yue",//"-"是不合法的,必須使用引號 firstName:"su" }2.檢索
1)檢索對象里包含的值:
obj["last-name"] //yue obj.firstName //su
2)用||填充默認(rèn)值
var name=obj.name||"susu";
3)用&&避免錯(cuò)誤
obj.likeInfo.model// throw "TypeError" obj.likeInfo && obj.likeInfo.model //undefined3.更新
通過賦值語句更新,如果有值則替換,沒有值則新增
obj.firstName="susu"4.引用
對象通過引用來傳遞。它們永遠(yuǎn)不會(huì)被復(fù)制
var x=obj; x.nick="aaa"; console.log(obj.nick);//aaa // x,obj指向同一個(gè)對象的引用 var a={},b={},c={}//a,b,c每個(gè)都引用一個(gè)不同的空對象 var a=b=c={};//a,b,c引用同一個(gè)空對象5.原型
每個(gè)對象都連接到一個(gè)原型對象,并從中繼承屬性
通過字面量創(chuàng)建的對象都連接到Object.prototype
object的create方法可以選擇某個(gè)對象作為它的原型
if(typeof Object.beget!=="function"){ Object.create=function(proto){ function F(){}; F.prototype=proto; return new F(); } } var a=Object.create(obj); // 當(dāng)對a對象做出改變時(shí),不會(huì)影響該對象的原型6.反射
檢查對象并確定對象的屬性
刪除不需要的屬性:
1) 檢查并丟棄值是函數(shù)的屬性
typeof obj.toString // "function"
2) hasOwnProperty 檢查對象自己的屬性,不會(huì)檢查原型鏈
obj.hasOwnProperty("toString") //false7.枚舉
for in:遍歷對象中的所有屬性名,包含原型中自己添加的屬性
注意:屬性名出現(xiàn)的順序是不確定的,(可以創(chuàng)建包含屬性名的數(shù)組,再用for循環(huán)來解決)
delete :刪除對象的屬性,不會(huì)觸及原型鏈中的任何對象
如果存在該屬性,則被移除,并返回true;
如果不存在該屬性,返回undefined;
// 不會(huì)影響原型 Object.prototype.name="1111111"; delete name;//true obj.name;//11111119.減少全局變量污染
最小化使用全局變量的方法之一:只創(chuàng)建一個(gè)唯一的全局變量
var local={ data:{}, methods:{ test(){ console.log(123) } } } local.methods.test();//123三、函數(shù) 1.函數(shù)對象
函數(shù)對象連接到Function.prototype(該原型對象本身連接到Object.prototype)
每個(gè)函數(shù)在創(chuàng)建時(shí)會(huì)附加兩個(gè)隱藏屬性:函數(shù)的上下文和實(shí)現(xiàn)函數(shù)行為的代碼。
每個(gè)函數(shù)對象在創(chuàng)建時(shí)也隨配有一個(gè)prototype屬性。它的值是一個(gè)擁有controctor屬性且值即為該函數(shù)的對象。
這和隱藏連接到Function.prototype完全不同。
函數(shù)對象通過函數(shù)字面量來創(chuàng)建:
var add=function(a,b){ return a+b; }
函數(shù)字面量包含四個(gè)部分:
1) 保留字function
2) 函數(shù)名:可以省略(匿名函數(shù)),可以用來遞歸調(diào)用自己,
3)參數(shù):
4) 函數(shù)主體
調(diào)用時(shí)每個(gè)函數(shù)接收兩個(gè)附加參數(shù):this,arguments。
調(diào)用模式:這些模式在如何初始化this上存在差異
1) 方法調(diào)用模式
當(dāng)一個(gè)函數(shù)被保存為對象的一個(gè)屬性時(shí),我們稱它為一個(gè)方法。
當(dāng)方法調(diào)用時(shí),this被綁定到該對象
var myObj={ value:0, increment:function(inc){ this.value+=typeof inc==="number"?inc:1; } } myObj.increment(2); console.log(myObj.value);//3
2) 函數(shù)調(diào)用模式
當(dāng)一個(gè)函數(shù)并非一個(gè)對象的屬性時(shí),那么它就是被當(dāng)作函數(shù)來調(diào)用的。
調(diào)用函數(shù)時(shí),this被綁定到全局對象。
var sum=add(3,4); //7
解決this指向:在外部函數(shù)中定義that=this,那么內(nèi)部函數(shù)可以通過that訪問外部的對象。
3) 構(gòu)造器調(diào)用模式
如果在一個(gè)函數(shù)前面帶上new來調(diào)用,那么背地里將會(huì)創(chuàng)建一個(gè)連接到該函數(shù)的prototype成員的新對象,
同時(shí)this會(huì)被綁定到新對象上。會(huì)改變r(jià)eturn語句的行為。
var Obj=function(str){ this.status=str; } Obj.prototype.get_status=function(){ return this.status; } var myobj=new Obj("aaa"); myobj.get_status();//aaa
4) apply調(diào)用模式
aplly(綁定給this的值,參數(shù)數(shù)組):構(gòu)建一個(gè)參數(shù)數(shù)組傳遞給調(diào)用函數(shù)
var statusObj={ status:123 } Obj.prototype.get_status.apply(statusObj);//1234.參數(shù)
當(dāng)函數(shù)調(diào)用時(shí),會(huì)接受一個(gè)附加參數(shù)arguments數(shù)組(類數(shù)組:有l(wèi)ength屬性,但沒有數(shù)組的任何方法)。
可以編寫一個(gè)無須指定參數(shù)個(gè)數(shù)的函數(shù)。
var sum=function(){ var sum=0; for(var i=0;i5.返回 return語句可用來使函數(shù)提前返回。
6.異常
如果使用構(gòu)造器調(diào)用(有new前綴),且返回不是一個(gè)對象,則返回this(該新對象)。異常是干擾程序的正常流程的不尋常
throw語句中斷函數(shù)的執(zhí)行,并拋出exception對象,該對象會(huì)被傳遞到try語句的catch從句。var add=function(a,b){ if(typeof a!=="number"||typeof b !=="number"){ throw{ name:"TypeError", message:"必須是數(shù)字" } } return a+b; } try{ add(1,"aaa") }catch(e){ console.log(e.name,e.message);//TypeError 必須是數(shù)字 }7.擴(kuò)充類型的功能通過給基本類型增加方法,新的方法立刻被賦予到所有對象的實(shí)例上,提高語言的表現(xiàn)力。
Function.prototype.method=function(name,func){ if(!this.prototype[name]){ this.prototype[name]=func; } return this; } Number.method("interge",function(){ return Math[this<0?"ceil":"floor"](this); }); 2.3.interge();//28.遞歸遞歸函數(shù)就是會(huì)直接或間接的調(diào)用自身的一種函數(shù)。
遞歸函數(shù)操作樹形結(jié)構(gòu),如瀏覽器端的文檔對象模型(DOM)// 漢諾塔游戲 var hanoi=function(n,from,ass,to){ if(n>0){ hanoi(n-1,from,to,ass); console.log("移動(dòng)第"+n+"個(gè)從"+from+"到"+to); hanoi(n-1,ass,from,to); } } hanoi(2,"A","B","C"); // 移動(dòng)次數(shù) function moveTimes(n){ if(n==1){ return 1; } return 2*moveTimes(n-1)+1; }9.作用域作用域控制著變量與參數(shù)的可見性及生命周期,它減少了名稱沖突,并提供了自動(dòng)內(nèi)存管理。
10.閉包
優(yōu)點(diǎn):內(nèi)部函數(shù)可以訪問定義它們的外部函數(shù)的參數(shù)和變量(除了this和arguments)。當(dāng)內(nèi)部函數(shù)被保存到外部時(shí),將會(huì)生成閉包。閉包會(huì)導(dǎo)致原有作用域鏈不釋放,造成內(nèi)存泄漏。
閉包可以訪問它被創(chuàng)建時(shí)所處的上下文環(huán)境。// 避免在循環(huán)中創(chuàng)建函數(shù),可以在循環(huán)之外創(chuàng)建一個(gè)輔助函數(shù), // 讓這個(gè)輔助函數(shù)再返回一個(gè)綁定了當(dāng)前i值的函數(shù) var add_handlers=function(nodes){ var helper=function(i){ return function(){ console.log(i); } } for(var i=0;i11.回調(diào) 發(fā)起異步請求時(shí),提供一個(gè)當(dāng)服務(wù)器的響應(yīng)到達(dá)時(shí)隨即觸發(fā)的回調(diào)函數(shù),異步函數(shù)立即返回,這樣客戶端就不會(huì)被阻塞。
12.模塊使用函數(shù)和閉包來構(gòu)造模塊。
模塊模式利用了函數(shù)作用域和閉包來創(chuàng)建被綁定對象與私有成員的關(guān)聯(lián)。
一般形式:一個(gè)定義了私有變量和函數(shù)的函數(shù);利用閉包創(chuàng)建可以訪問私有變量和函數(shù)的特權(quán)函數(shù);最后返回這個(gè)特權(quán)函數(shù),或者保存到一個(gè)可訪問到的地方。String.method("deentityify",function(){ // 字符實(shí)體表,若放在函數(shù)內(nèi)部每次執(zhí)行函數(shù)時(shí)該字面量都會(huì)被求值一次,會(huì)帶來運(yùn)行時(shí)的損耗, var entity={ quot:""", lt:"<", gt:">", } return function(){ return this.replace(/&([^&;]+);/g,function(a,b){ var r=entity[b]; return typeof r==="string"?r:a; }) } }()) ">"<".deentityify(); // >"<13.級聯(lián)如果方法返回this,就會(huì)啟用級聯(lián)。
14.柯里化
在一個(gè)級聯(lián)中,可以在多帶帶一條語句中依次調(diào)用同一個(gè)對象的很多方法。柯里化允許我們把函數(shù)與傳遞給它的參數(shù)相結(jié)合,產(chǎn)生一個(gè)新的函數(shù)。
Function.method("curry",function(){ var slice=Array.prototype.slice, args=slice.apply(arguments); that=this; return function(){ return that.apply(null,args.concat(slice.apply(arguments))); } }); function add(a,b){ return a+b; } var add1=add.curry(1); var res=add1(6);//715.記憶記憶:函數(shù)可以將先前操作的結(jié)果記錄在某個(gè)對象里,從而避免無謂的重復(fù)運(yùn)算。
// memo:初始數(shù)組; formula:函數(shù) 公式 var memoizer=function(memo,formula){ var recur=function(n){ result=memo[n]; if(typeof result !=="number"){ result=formula(recur,n); memo[n]=result; } return result; } return recur; } var fibonacci=memoizer([0,1],function(recur,n){ return recur(n-1)+recur(n-2); }); var res=fibonacci(10);四、繼承 1.偽類缺點(diǎn):沒有私有環(huán)境,所有的屬性都是公開的。
// 當(dāng)采用構(gòu)造器調(diào)用模式,函數(shù)執(zhí)行的方式會(huì)被修改。 // 如果new運(yùn)算符是一個(gè)方法,它可能會(huì)像這樣執(zhí)行 Function.method("new",function(){ // 創(chuàng)建一個(gè)新對象,它繼承自構(gòu)造器的原型對象 var that=Object.create(this.prototype); // 調(diào)用構(gòu)造器函數(shù),綁定this到新對象上 var other=this.apply(that,arguments); // 如果它的返回值不是一個(gè)對象,就返回改新對象 return (typeof other=="object"&& other)||that; })可以構(gòu)造一個(gè)偽類來繼承父類,這是通過定義它的constructor函數(shù)并替換它的prototype為一個(gè)父類的實(shí)例來實(shí)現(xiàn)
Function.method("inherits",function(Parent){ this.prototype=new Parent(); return this; })2.對象說明符在編寫構(gòu)造器時(shí)讓它接受一個(gè)簡單的對象說明符。
多個(gè)參數(shù)可以按任何順序排列,如果構(gòu)造器使用默認(rèn)值,一些參數(shù)可以忽略,代碼易閱讀。var obj=testFn({ first:f, middle:m, last:l });3.原型一個(gè)新對象可以繼承一個(gè)舊對象的屬性
用Object.create(parent)構(gòu)造出更多的實(shí)例
差異化繼承:通過定制一個(gè)新對象,我們指明它與所基于的基本對象的區(qū)別// 作用域繼承,內(nèi)部作用域繼承外部作用域遇到一個(gè)左花括號時(shí)block函數(shù)被調(diào)用, var block=function(){ // 記住當(dāng)前作用域,構(gòu)造一個(gè)包含了當(dāng)前作用域中所有對象的新作用域 var oldScope=scope; scope=Object.create(oldScope); // 傳遞左花括號作為參數(shù)調(diào)用advance advance("{"); // 使用新的作用域進(jìn)行解析 parse(scope); // 傳遞左花括號作為參數(shù)調(diào)用advance并拋棄新作用域,恢復(fù)原來老的作用域。 advance("}"); scope=oldScope; }4.函數(shù)化應(yīng)用模塊模式解決私有變量和私有函數(shù)
函數(shù)化構(gòu)造器步驟:
1)創(chuàng)建一個(gè)新對象
2)有選擇的定義私有實(shí)例變量和方法。
3)給這個(gè)對象擴(kuò)充方法,這些方法擁有特權(quán)去訪問參數(shù)。
4)返回那個(gè)新對象// 偽代碼模板 var constructor=function(spec,my){ var that,其他的私有實(shí)例變量 my=my||{}; 把共享的變量和函數(shù)添加到my中 that=一個(gè)新對象 添加給that的特權(quán)方法 return that; }// 處理父類的方法 Object.method("superior",function(name){ var that=this, method=that[name]; return function(){ return method.apply(that,arguments); } })//例子 var mammal=function(spec){ var that={}; that.get_name=function(){ return "hello"+spec.name; } return that; } var cat=function(spec){ var that=mammal(spec); var super_get_name=that.superior("get_name") that.get_name=function(){ return spec.name+"like"+super_get_name(); } return that; } var my=cat({name:"su"}); console.log(my.get_name());//su like hello su5.部件從一套部件中把對象組裝出來。
五、數(shù)組 1.定義:字面量: var arr=[1,2,3];
構(gòu)造方法: new Array(length/content);
2.屬性constructor: 返回創(chuàng)建此對象的數(shù)組函數(shù)的引用。
length:設(shè)置或返回?cái)?shù)組中元素的長度。
prototype:向?qū)ο筇砑訉傩院头椒?/p> 3.刪除
1)delete 會(huì)在數(shù)組中留下一個(gè)空洞
2)splice 可以刪除元素并替換為其他元素var arr=["a","b","c","d"]; delete arr[1]; console.log(arr);//["a", empty, "c", "d"] // 對于大型數(shù)據(jù),可能效率會(huì)不高 var arr1=["a","b","c","d"]; arr1.splice(2,1) console.log(arr1);//["a", "b", "d"]4.方法
Array.method("reduce",function(f,value){ for(var i=0;iObject.create方法用在數(shù)組是沒有意義的,因?yàn)樗a(chǎn)生一個(gè)對象,而不是一個(gè)數(shù)組。
5.指定初始值
產(chǎn)生的對象將繼承這個(gè)數(shù)組的值和方法,但是它沒有那個(gè)特殊的length屬性。// fill 初始化 var arr=new Array(5); arr.fill(0);//[0, 0, 0, 0, 0] // 初始化一維數(shù)組 Array.dim=function(dimension,initial){ var a=[]; for(var i=0;i6.原型-方法 1).改變原數(shù)組:
push:向數(shù)組的末尾添加一個(gè)或更多元素,并返回新的長度。
pop:刪除并返回?cái)?shù)組的最后一個(gè)元素
shift: 刪除并返回?cái)?shù)組的第一個(gè)元素
unshift:向數(shù)組開頭添加一個(gè)或多個(gè)元素,并返回新的長度。
reverse:逆轉(zhuǎn)順序,并返回新數(shù)組
sort:排序,返回排序后的數(shù)組
splice:(從第幾位開始,截取多少的長度,在切口處添加新的數(shù)據(jù)) 刪除元素,并向數(shù)組添加新元素,返回被截取元素的數(shù)組
fill(value, start, end) 將一個(gè)固定值替換數(shù)組的元素。
2).不改變原數(shù)組
concat: 連接兩個(gè)或更多的數(shù)組,并返回結(jié)果。
slice:(從該位開始截取,截取到該位] 截取,返回被截取元素的數(shù)組
join:通過指定的分隔符(默認(rèn)逗號)進(jìn)行分隔,返回字符串
toString:把數(shù)組轉(zhuǎn)換為字符串,并返回結(jié)果。
7.原型-循環(huán)方法1)參數(shù)相同 (回調(diào)函數(shù)(當(dāng)前元素,當(dāng)前元素的索引,原數(shù)組),this)
forEach: 代替普通for循環(huán),沒有返回值
map:通過指定函數(shù)處理數(shù)組的每個(gè)元素,并返回處理后的數(shù)組。
filter:過濾 ,返回符合條件所有元素的數(shù)組。
every:檢測數(shù)值中的每個(gè)元素是否都符合條件。返回true或false
some:檢測數(shù)組中是否有元素符合條件。返回true或false
5.應(yīng)用1.數(shù)組-參考手冊
六、正則表達(dá)式 1.結(jié)構(gòu)
2.數(shù)組,類數(shù)組
3.forEach,for in ,for of的區(qū)別1)創(chuàng)建RegExp對象:
字面量 var my_reg=/[A-Z]/g;
構(gòu)造器,適用于必須在運(yùn)行時(shí)動(dòng)態(tài)生成正則表達(dá)式的情形。var my_reg=new RegExp("[A-Z]","g");
創(chuàng)建字符串時(shí)需要注意,因?yàn)榉葱备茉谡齽t表達(dá)式和字符串中含義不同,通常需要雙寫反斜杠,以及對引號進(jìn)行轉(zhuǎn)義2)正則表達(dá)式標(biāo)識
標(biāo)識 含義 g 全局的(匹配多次;不同的方法對g標(biāo)識的處理各不相同) i 大小寫不敏感(忽略字符大小寫) m 多行(^和$能匹配行結(jié)束符) 3)RegExp對象的屬性
2.元素
屬性 用法 global 如果標(biāo)識g被使用,值為true ignoreCase 如果標(biāo)識i被使用,值為true multiline 如果標(biāo)識m被使用,值為true lastIndex 下一次exec匹配開始的索引。初始值為0 source 正則表達(dá)式源碼文本 1)正則表達(dá)式分支
一個(gè)正則表達(dá)式包含一個(gè)或多個(gè)正則表達(dá)式序列。
這些序列被|(豎線)字符分隔,如果這些字符中的任何一項(xiàng)符合匹配條件,那么這個(gè)選擇就被匹配。
它常是按順序依次匹配這些序列項(xiàng)// 因?yàn)閕n已被成功匹配,所以不會(huì)匹配int var a="into".match(/in|int/);//["in"]2)正則表達(dá)式序列
一個(gè)正則表達(dá)式序列包含一個(gè)或多個(gè)正則表達(dá)式因子。
每個(gè)因子能選擇是否跟隨一個(gè)量詞,這個(gè)量詞決定著這個(gè)因子被允許出現(xiàn)的次數(shù)。
如果沒有指定這個(gè)量詞,那么該因子只會(huì)被匹配一次3)正則表達(dá)式因子
一個(gè)正則表達(dá)式因子可以是一個(gè)字符、一個(gè)由圓括號包圍的組、一個(gè)字符類,或是一個(gè)轉(zhuǎn)義序列
這些字符需要轉(zhuǎn)義: / { } ? + * | . ^ $4)正則表達(dá)式轉(zhuǎn)義
反斜杠字符在正則表達(dá)式因子和在字符串中均表示轉(zhuǎn)義,但在正則表達(dá)式因子中有點(diǎn)不同
d : [0-9],D:[^d]
s : [tnrvf ] 空白字符, S:[^s]
w : [0-9A-Za-z_] ,W:[^w]
: 單詞邊界 B:[^b]
1 : 指向分組1所捕獲到的文本的一個(gè)引用。 如:2,35)正則表達(dá)式分組
捕獲型: 一個(gè)捕獲型分組是一個(gè)被包圍在圓括號找那個(gè)的正則表達(dá)式分支。每個(gè)捕獲型分組都被指定了一個(gè)數(shù)組。
任何匹配這個(gè)分組的字符都會(huì)被匹配。
在正則表達(dá)式中第一個(gè)捕獲(的是分組1,第二個(gè)捕獲(的是分組2。非捕獲型: 非捕獲型分組有一個(gè)(?:前綴,僅做簡單的匹配,并不會(huì)捕獲所匹配的文本,不會(huì)干擾捕獲型分組的編號。
向前正向匹配: 向前正向匹配分組有一個(gè)(?=前綴,類似非捕獲型分組,
但在這個(gè)組匹配后,文本會(huì)倒回到它開始的地方,實(shí)際上并不匹配任何東西。向前負(fù)向匹配: 向前負(fù)向匹配分組有一個(gè)(?!前綴,類似向前正向匹配分組,
但只有當(dāng)它匹配失敗時(shí)它才繼續(xù)向前進(jìn)行匹配6)正則表達(dá)式字符集
正則表達(dá)式字符集是一種指定一組字符的便利方式。
如果匹配一個(gè)元音字母,可以寫成(?:a|e|i|o|u),
但可以更方便的寫成一個(gè)類[aeiou], 類的求反 [^aeiou]7)正則表達(dá)式量詞
正則表達(dá)式因子可以用一個(gè)正則表達(dá)式量詞后綴來決定這個(gè)因子應(yīng)該被匹配的次數(shù)。
七、方法 1.Array
包圍在一對花括號中的一個(gè)數(shù)組表示這個(gè)因子被匹配的次數(shù)。
n+ : {1,} 1到多個(gè)
n* : {0,}
n? : {0,1}
n{X} : X個(gè)
n{X,Y} : X-Y個(gè)
n{X,} : X到多個(gè)
?=n : 匹配其后緊接n 的字符串
?!n : 匹配其后沒有緊接n 的字符串
如果只有一個(gè)量詞,表示趨向于進(jìn)行貪婪性匹配,即匹配盡可能多的副本直至達(dá)到上限。
如果這個(gè)量詞附加一個(gè)后綴?,表示趨向于進(jìn)行非貪婪性匹配,即只匹配必要的副本就好。數(shù)組-參考手冊
2.Functionfunction.apply(thisArg,argArray)
apply方法調(diào)用function,傳遞一個(gè)會(huì)被綁定到this上的對象和一個(gè)可選的數(shù)組作為參數(shù)Function.method("bind",function(that){ var method=this; var slice=Array.prototype.slice; var args=slice.apply(arguments,[1]) return function(){ return method.apply(that,args.concat(slice.apply(arguments))); } }) var test=function(){ return this.value+":"+Array.prototype.slice.apply(arguments); }.bind({value:666},1,2); console.log(test(3));//666:1,2,33.NumberNumber-參考手冊
4.ObjectObject.hasOwnProperty(name)不會(huì)檢查原型鏈中的屬性
var a={member:true}; var b=Object.create(a); var c=a.hasOwnProperty("member");//true var d=b.hasOwnProperty("member");//false var e=b.member;//true5.RegExpRegExp-參考手冊
1.regExp.exec(string)
如果通過循環(huán)去查詢一個(gè)匹配模式在字符串中發(fā)生了幾次,需要注意:如果提前退出了循環(huán),再次進(jìn)入這個(gè)循環(huán)前必須把
RegExp.lastIndex重置為0,而且,^僅匹配RegExp.lastIndex為0的情況。
如果帶有g(shù)全局標(biāo)識,查找不是從這個(gè)字符串的起始位置開始,而是從regExp.lastIndex位置開始。var reg1=/ab/g; var str="ababab"; console.log(reg1.exec(str),reg1.lastIndex) console.log(reg1.exec(str),reg1.lastIndex) console.log(reg1.exec(str),reg1.lastIndex) console.log(reg1.exec(str),reg1.lastIndex) console.log(reg1.exec(str),reg1.lastIndex) // 打印結(jié)果: ["ab", index: 0, input: "ababab", groups: undefined] 2 ["ab", index: 2, input: "ababab", groups: undefined] 4 ["ab", index: 4, input: "ababab", groups: undefined] 6 null 0 ["ab", index: 0, input: "ababab", groups: undefined] 22.regExp.test(string)
// 如果這個(gè)方法使用g標(biāo)識,會(huì)改變lastIndex的值 var reg=/[A-Z]/g; var arr=["Asdsd","BsdsCds","Dasas","E1212"]; for(var i=0;i6.String 字符串-參考手冊
附錄A-毒瘤 1.全局變量全局變量使得在同一個(gè)程序中運(yùn)行獨(dú)立的子程序變得更難。
因?yàn)槿肿兞靠梢员怀绦虻娜魏尾糠衷谌我鈺r(shí)間修改,使程序的行為變得極度復(fù)雜,降低程序的可靠性// 定義全局變量的方法 var foo=value; window.foo=value; foo=value;2.作用域沒有塊級作用域,代碼塊中聲明的變量在包含此代碼塊的函數(shù)的任何位置都是可見的。
3.自動(dòng)插入分號
更好的方式:在每個(gè)函數(shù)的開頭部分聲明所有變量有一個(gè)自動(dòng)修復(fù)機(jī)制,它試圖通過自動(dòng)插入分號來修正有缺損的程序.
它可能會(huì)掩蓋更為嚴(yán)重的錯(cuò)誤。// 在return語句后自動(dòng)插入分號導(dǎo)致的后果 function test1(){ return{ name:"aaa" } } function test2(){ return { name:"aaa" } } console.log(test1(),test2());//{name: "aaa"} undefined4.保留字保留字不能被用來命名變量或參數(shù)。
當(dāng)保留字被用做對象字面量的鍵值時(shí),它們必須被引號括起來,不能用在點(diǎn)表示法中,必須使用括號表示法。var case;//非法,都不支持 // ie8及以下不支持 非法的寫法 var obj={case:"123"};//非法 var a=obj.case//非法 var object={"case":"1212"};//ok var b=object["case"];//ok5.UnicodeUnicode把一對字符視為一個(gè)單一的字符,而js認(rèn)為一對字符是兩個(gè)不同的字符
6.typeoftypeof null返回object
正則表達(dá)式,返回object,在safari(3.x版本)中返回function// 區(qū)分null與對象 if(value&& typeof value=="object"){ //value是一個(gè)對象或數(shù)組 }7.parseIntparseInt把字符串轉(zhuǎn)換為整數(shù),
// 遇到非數(shù)字時(shí)會(huì)停止解析 parseInt("16")==parseInt("16aa123");//ture // ie8及以下會(huì)出現(xiàn)以下問題: // 如果字符串第一個(gè)字符是0,那么字符串會(huì)基于八進(jìn)制來求值,() // 會(huì)導(dǎo)致程序解析日期和時(shí)間時(shí)出現(xiàn)問題,可以用parseInt的第二個(gè)參數(shù)作為基數(shù)解決 console.log(parseInt("08"),parseInt("09"));//0 0 console.log(parseInt("08",10),parseInt("09",10));//8 98.++運(yùn)算符可以用于加法運(yùn)算或字符串連接,如何執(zhí)行取決于其參數(shù)的類型
9.浮點(diǎn)數(shù)
加法運(yùn)算:兩個(gè)運(yùn)算數(shù)都是數(shù)字
字符串連接:其中一個(gè)運(yùn)算數(shù)是空字符串,則另一個(gè)運(yùn)算數(shù)被轉(zhuǎn)換成字符串進(jìn)行連接。二進(jìn)制的浮點(diǎn)數(shù)不能正確處理十進(jìn)制的小數(shù)。
0.1+0.2 //0.30000000000000004 //浮點(diǎn)數(shù)中的整數(shù)運(yùn)算是正確的,所以小數(shù)表現(xiàn)出來的錯(cuò)誤可以通過指定精度來避免 (0.1*10+0.2*10)/10 //0.310.NaNNaN是一個(gè)特殊的數(shù)量值。它表示的不是一個(gè)數(shù)字,但是 typeof NaN==="number"
該值會(huì)在試圖把非數(shù)字形式的字符串轉(zhuǎn)化為數(shù)字時(shí)產(chǎn)生,如:Number("12px") //NaN
NaN===NaN //fales// 區(qū)分?jǐn)?shù)字與NaN isNaN(NaN);//true isNaN("aaa");//true判斷一個(gè)值是否可用做數(shù)字使用isFinite函數(shù),因?yàn)樗鼤?huì)篩掉NaN和Infinity
但是它會(huì)試圖把運(yùn)算數(shù)轉(zhuǎn)換為一個(gè)數(shù)字,isFinite("10")//truevar isNumber=function(value){ return typeof value==="number"&&isFinite(value) } isNumber("10");//false11.偽數(shù)組// 辨別數(shù)組 // arguments是一個(gè)類數(shù)組,返回[object Arguments] if(Object.prototype.toString.apply(value)==="[object Array]"){ //value是一個(gè)數(shù)組 }12.假值以下這些值全部等同于假,但它們是不可互換的
13.hasOwnProperty
值 類型 0 Number NaN(非數(shù)字) Number ""(空字符串) String false Boolean null Object undefined Undefined hasOwnProperty可以解決for in的隱患
但它是一個(gè)方法,在任何對象中,它可能會(huì)被一個(gè)不同的函數(shù)甚至一個(gè)非函數(shù)的值所替換var name,obj={}; obj.hasOwnProperty=null;//地雷 for(name in obj){ if(obj.hasOwnProperty(name)){//觸雷 console.log(name,obj[name]) } }14.對象js對象永遠(yuǎn)不會(huì)是真的空對象,因?yàn)樗梢詮脑椭腥〉贸蓡T屬性
// 如果字符串里面包含constructor,會(huì)返回{hello: 3, word: 1, constructor: "function Object() { [native code] }1"} // 可以用hasOwnProperty處理 返回{hello: 1, word: 1, constructor: 1} var text="hello word hello,Hello constructor"; var words=text.toLowerCase().split(/[s,.]+/); var count={},word; for(var i=0;i附錄B-糟粕 1.== ==,!=運(yùn)算符只有在兩個(gè)運(yùn)算類型一致時(shí)才會(huì)做出正確的判斷,如果兩個(gè)運(yùn)算數(shù)是不同的類型,它們試圖去強(qiáng)制轉(zhuǎn)換值的類型
==,!=運(yùn)算符缺乏傳遞性,所以使用===和!=="" == "0"http://false 0 == "0" //true false == "false"http://false false == "0" //true false == undefined //false false == null //fasle null == undefined //true " " == 0 //true2.with語句with語句本意是用來快捷的訪問對象的屬性,但有時(shí)不可預(yù)料,所以應(yīng)該避免使用它
嚴(yán)重影響了js處理器的速度,因?yàn)樗钄嗔俗兞棵脑~法作用域綁定with(obj){ a=b; } // 和下面的代碼做的是同樣的事情 if(obj.a===undefined){ a = obj.b === undefined ? b : obj.b; }else{ obj.a = obj.b === undefined ? b : obj.b; } // 所以,它等同于這些語句中的某一條: a = b; a = obj.b; obj.a = b; obj.a = obj.b;3.evaleval函數(shù)傳遞一個(gè)字符串給javaScript編輯器,并且執(zhí)行結(jié)果
4.continue語句
1)使用eval形式的代碼更加難以閱讀,這種形式使得性能顯著降低,因?yàn)樗枰\(yùn)行編譯器,但也許只是為了執(zhí)行一個(gè)賦值語句。
2)它會(huì)讓JSLint失效,讓此工具檢測問題的能力大打折扣
3)減弱了應(yīng)用程序的安全性,因?yàn)樗磺笾档奈谋臼谟枇颂嗟臋?quán)利,與with語句執(zhí)行方式一樣,降低語言的性能
4)Function構(gòu)造器是eval的另一種形式,應(yīng)該避免使用(new Function ([arg1[, arg2[, ...argN]],] functionBody))
5)setTimeout,setInterval當(dāng)接收字符串參數(shù)時(shí),也會(huì)像eval那樣處理,應(yīng)避免使用字符串參數(shù)continue語句跳到循環(huán)的頂部
但是如果一段代碼通過重構(gòu)移除continue語句之后,性能都會(huì)得到改善console.time(111) var sum=0; for(var i=0;i<100;i++){ if(i==50){ continue; } sum+=i; } console.timeEnd(111);//0.051025390625ms console.time(222) var sum=0; for(var i=0;i<100;i++){ if(i!=50){ sum+=i; } } console.timeEnd(222);// 0.02099609375ms5.switch穿越除非你明確地中斷流程,否則每次條件判斷后都穿越到下一個(gè)case條件。
6.缺少塊的語句if,while,do,for語句可以接受一個(gè)括在花括號找那個(gè)的代碼塊,也可以接受單行語句
但是單行語句模糊了程序的結(jié)構(gòu),使得在隨后的操作代碼中可能很容易插入錯(cuò)誤//容易導(dǎo)致錯(cuò)誤 if(ok) t=true; advance()7.++這兩個(gè)運(yùn)算符鼓勵(lì)了一種不夠謹(jǐn)慎的變成風(fēng)格,大多數(shù)的緩沖區(qū)溢出的錯(cuò)誤所造成的安全漏洞,都是由像這樣的代碼導(dǎo)致的
8.位運(yùn)算符
并且它會(huì)使代碼變得過于擁擠,復(fù)雜和隱晦在java里,位運(yùn)算符處理的是整數(shù),但是js沒有整數(shù)類型,只有雙精度的浮點(diǎn)數(shù),因此,位操作符把它們的數(shù)字運(yùn)算數(shù)先轉(zhuǎn)換成整數(shù),在執(zhí)行運(yùn)算,然后在轉(zhuǎn)換回去。
9.function語句對比function表達(dá)式
在大多數(shù)語言中,位運(yùn)算符接近于硬件處理,所以非常快。但js的執(zhí)行環(huán)境一般接觸不到硬件,所以非常慢,js很少被用來執(zhí)行位操作function語句在解析時(shí)會(huì)發(fā)生被提升的情況,不管function被放置在哪里,它會(huì)被移動(dòng)到被定義時(shí)所在作用域的頂層,
這放寬了函數(shù)先聲明后使用的要求,這會(huì)導(dǎo)致混亂function foo(){ } // foo是一個(gè)包含一個(gè)函數(shù)值的變量,函數(shù)就是數(shù)值 var foo=function(){ }一個(gè)語句不能以一個(gè)函數(shù)表達(dá)式開頭,但可以把函數(shù)調(diào)用括在一個(gè)圓括號之中
(function(){ var a=1; // 這個(gè)函數(shù)可能對環(huán)境有一些影響,但不會(huì)引入新的全局變量 })()10.類型的包裝對象new Boolean,new Number,new String會(huì)返回一個(gè)對象,該對象有一個(gè)valueOf方法會(huì)返回被包裝的值
11.new
避免使用new Array和new Object,可使用[]和{}來代替1)new運(yùn)算符創(chuàng)建一個(gè)繼承于其構(gòu)造器函數(shù)的原型的新對象,然后調(diào)用該構(gòu)造器函數(shù),把新創(chuàng)建的對象綁定給this,
12.void
這給構(gòu)造器函數(shù)一個(gè)機(jī)會(huì)在返回給請求者前自定義新創(chuàng)建的對象
2)如果忘記new運(yùn)算符,就是一個(gè)普通的函數(shù)調(diào)用,this被綁定到全局對象,而不是創(chuàng)建一個(gè)新對象。污染全局變量
3)構(gòu)造器函數(shù)應(yīng)該以首字母大寫的形式命名,并且首字母大寫的形式應(yīng)該只用于來命名構(gòu)造器函數(shù)在很多語言中,void是一種類型,表示沒有值
但在js中,void是一個(gè)運(yùn)算符,它接受一個(gè)運(yùn)算數(shù)并返回undefined,這沒有什么用,應(yīng)避免使用它//當(dāng)用戶鏈接時(shí),void(0) 計(jì)算為 0,但 Javascript 上沒有任何效果。 單擊此處什么也不會(huì)發(fā)生
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/102933.html
摘要:調(diào)用函數(shù)時(shí),被綁定到全局對象。如果使用構(gòu)造器調(diào)用有前綴,且返回不是一個(gè)對象,則返回該新對象。閉包會(huì)導(dǎo)致原有作用域鏈不釋放,造成內(nèi)存泄漏。當(dāng)采用構(gòu)造器調(diào)用模式,函數(shù)執(zhí)行的方式會(huì)被修改。 內(nèi)容 ECMAScript核心語法結(jié)構(gòu):1.語法2.對象3.函數(shù)4.繼承5.數(shù)組6.正則表達(dá)式7.方法8.附錄A-毒瘤9.附錄B-糟粕 一、語法 1.類型、值和變量 1) 類型:區(qū)分?jǐn)?shù)據(jù)類型 在JS中使...
摘要:前端入門的門檻相對較低,學(xué)習(xí)曲線是越來越陡峭,由淺入深,可以分為四個(gè)階段。第二階段高級程序設(shè)計(jì)有的書是用來成為經(jīng)典的,比如犀牛書還有些書是用來超越經(jīng)典的,顯然這本書就是。接下來可以看看教程,看看源代碼,嘗試著寫一寫這些效果。 前端入門的門檻相對較低,學(xué)習(xí)曲線是越來越陡峭,由淺入深,可以分為四個(gè)階段。 第一階段:《JavaScript DOM編程藝術(shù)》 看這本書之前,請先確認(rèn)你對J...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書清單也要收費(fèi)。這本書便從的異步編程講起,幫助我們設(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書清單也要收費(fèi)。這本書便從的異步編程講起,幫助我們設(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
閱讀 1772·2023-04-25 21:50
閱讀 2419·2019-08-30 15:53
閱讀 767·2019-08-30 13:19
閱讀 2743·2019-08-28 17:58
閱讀 2465·2019-08-23 16:21
閱讀 2700·2019-08-23 14:08
閱讀 1374·2019-08-23 11:32
閱讀 1439·2019-08-22 16:09