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