對象的特性:es6
1.惟一標識性,即便徹底不同的對象,內存地址也不一樣,因此他們不相等正則表達式
2.對象具備狀態,同一個對象可能處在不一樣狀態下數組
3.對象具備行爲,即對象的狀態可能由於他的行爲產生變遷瀏覽器
Js直到es6以前,有對象的概念,可是沒有類的概念。安全
對象的分類:閉包
1.內建對象app
- 用Es標準中定義的對象,在任何的Es的實現中均可以使用(好比:Math,String,Number,Boolean,Function...)dom
2.宿主對象函數
-用Js運行環境提供的對象,目前來說主要是指用瀏覽器提供的對象(BOM,DOM)(console.log/document.write)工具
3.自定義對象
-開發人本身定義的對象
-建立對象
在對象中保存的值稱爲屬性
對象的屬性值能夠是任何數據類型,也能夠是個函數(刪除對象的屬性:delete obj.name)
當函數做爲對象的屬性時,咱們稱這個函數爲這個對象的方法,調用這個函數就是調用對象的方法,僅僅是名稱上的區別
枚舉對象中的屬性 使用for..in語句(語法:for(var 變量 in 對象)
//對象中有幾個屬性就會執行幾回,每次執行時,會將屬性的名字賦值給變量
使用工廠方法建立對象
-經過該方法能夠大批量的建立對象
-使用工廠建立的對象,使用的構造函數都是Object,因此致使建立的對象都是Object這個類型,就致使咱們沒法區分出多種不一樣類型的對象
function creatDog(name,age){
使用構造函數建立對象
-構造函數就是一個普通的函數,建立方式和普通函數沒有區別,
-不一樣的是構造函數習慣首字母大寫
-構造函數和普通函數的區別就是調用方式的不一樣,普通函數是直接調用,而構造函數須要使用new關鍵字來調用
function creatPerson(name,age){
this.name=name;
this.age=age;
this.say=function(){
alert('hello'+name);
}
}
var obj=new creatPerson("Jeo",23);
var obj2=new creatPerson("Rose",14);
obj.say();
構造函數的執行流程:
1.當即建立一個新的對象
2.將新建的對象設置爲函數中this,在構造函數中可使用this來引用新建的對象
function Person(){
alert(this);
}
var per=new Person();//object,就是新建立的對象:per
3.順序執行代碼
4.將新建對象做爲返回值返回
function Person(){
}
var per=Person();
console.log(per);//undefined,做爲普通函數調用,沒有返回值
var per1=new Person();
console.log(per1);//object
- 使用同一個構造函數建立對象,咱們稱爲一類對象,將一個構造函數稱爲一個類
- 將構造函數建立的對象,稱爲該類的實例
使用instanceof能夠檢查一個對象是不是一個類(構造函數)的實例
-語法:對象instanceof構造函數(是:true)
全部的對象都是Object的後代
建立一個Person構造函數
- 在Person構造函數中,爲每個對象都添加了一個say方法,
- 目前咱們的方法是在構造函數內部執行建立的,也就是構造函數每執行一次就會建立一個新的say方法(即每一個實例的say()都是惟一的
解決方法:
- 將say()方法定義在全局做用域
function creatPerson(name,age){
this.name=name;
this.age=age;
this.say=fun;
}
function fun(){
alert('hello:'+this.name);
}
var obj=new creatPerson("Jeo",23);
var obj2=new creatPerson("Rose",14);
obj.say();
缺點:
-將函數定義在全局做用域,污染了全局做用域的命名空間
-定義在全局做用域中也很不安全
解決方案:
原型prototype
咱們所建立的每個函數,解析器都會向函數中添加一個屬性prototype
-若是函數做爲普通函數調用prototype沒有任何做用
-當函數經過構造函數調用時,它所建立的對象中都有一個隱含的屬性
-指向構造函數的原型對象,咱們能夠經過__proto__來訪問該屬性
-原型對象就至關於一個公共區域,全部同一個類的實例均可以訪問到這個原型對象
-咱們能夠將對象中共有的內容,統一設置到原型對象中
-當咱們在訪問對象的一個屬性或方法時,它會事先在對象自身中尋找,若是有則直接使用,若是沒有則會去原型對象中尋找,若是找到則直接使用
之後建立構造函數時,能夠將這些對象共有的屬性和方法,統一添加到構造函數中的原型對象中,這樣不用分別爲每個對象添加,也不會影響到全局做用域,就可使每一個對象都具備這些屬性和方法
function Hello(){
}
Hello.prototype.a="hello";
var hel1=new Hello();
//hel1.a="我是hel1";
console.log(hel1.a);
當程序這樣運行時控制檯輸出 hello
當程序去掉註釋時,會輸出 「我是hel1」
故修改say()方法,變成原型對象的方法
function creatPerson(name,age){
this.name=name;
this.age=age;
}
creatPerson.prototype.say=function(){
alert("hello:"+this.name);
}
var obj=new creatPerson("Jeo",23);
var obj2=new creatPerson("Rose",14);
obj.say();//hello:Jeo
檢查一個對象是否含有某個屬性(in),若對象中沒有,原型中有則也返回true
檢查一個對象是否含有某個屬性(hasOwnProperty),只有對象自身含有屬性時,纔會返回true
function Test(){
}
Test.prototype.name="我是原型中的名字";
var test=new Test();
alert("name" in test);//true
----------------------------------------------
原型對象也是對象,因此它也有原型(原型鏈)
- 當咱們使用一個對象的屬性或方法時,會先在自身中尋找,自身中若是有,則直接使用,若是沒有則去原型對象中尋找,若原型對象中有,則使用,若沒有則去原型對象的原型中尋找,直到找到Object對象的原型,Object對象的原型沒有原型,若在Object中依然沒有找到,則返回undefined
var Person=function(name,age){ this.name=name; this.age=age; } Person.prototype.getAge=function(){ return this.age;} var per=new Person('Jeo',18); console.log(per.getAge());//18
關於原型鏈中一些結論:
__proto__
指向 Function.prototype
;prototype
指向 instance.__proto__
;(實例的)__proto__
指向 Object.prototype
;prototype
屬性;ob.__proto__
, 也就是訪問該對象的構造函數的原型 obCtr.prototype
,若仍找不到,會繼續查找 obCtr.prototype.__proto__
,像依次查找下去。若在某一刻,找到了該屬性,則會馬上返回值並中止對原型鏈的搜索,若找不到,則返回 undefined。
針對上述結論:分別理解這兩個代碼:
Js中的繼承分爲兩種接口繼承和實現繼承。接口繼承只繼承方法簽名,而實現繼承則繼承實際方法,因爲函數沒有簽名,在ECMAScript中沒法實現接口繼承,ECMAScript只支持實現繼承,並且其實現繼承主要是依靠原型鏈來實現的。
原型鏈:
是實現繼承的主要方法,其基本思想是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法。其中,每一個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針
原型繼承:經過__proto__並藉助prototype來實現
var Person=function(name,age){
this.name=name; this.age=age; } Person.prototype.getAge=function(){ return this.age;} var per=new Person(Jeo,18); console.log(per.getAge());//18
首先這段代碼裏,per.__proto__指向Person.prototype,經過原型來構造函數,
var Person=function(name,age){ this.name=name; this.age=age; } Person.prototype.getAge=function(){ return this.age;} //var per=new Person(Jeo,18); //console.log(per.getAge());//18 function Work(name,age,job){ Person.call(this,name,age); this.job=job; } //Work.prototype=Person.prototype; (1) Work.prototype=Object.create(Person.prototype);(2)
Work.prototype.constructor=Work;//調整constructor,以避免constuctor錯誤
var per=new Work('Jeo',18,'doctor'); console.log(per);
咱們發現用這種方法實現了原型鏈的繼承,在f12中調試能夠看到以下
執行(1)中代碼獲得第一個Work的狀況,執行(2)獲得第二,她們的原型對象是不一樣的
垃圾回收
-程序運行過程當中會產生垃圾(這些垃圾積攢過多之後,會致使程序運行的速度過慢,因此咱們須要一個垃圾回收的機制,來處理程序運行過程當中產生的垃圾)
-當一個對象沒有任何的變量或屬性對它進行引用,此時,咱們將永遠沒法操做該對象(此對象就好似一個垃圾,這種對象過多會佔用大量的內存空間,致使程序運行變慢,因此這種垃圾必須進行清理
- 在JS中擁有自動的垃圾回收機制,會自動將這些垃圾對象從內存中銷燬,咱們不須要也不能進行垃圾回收的操做
-咱們須要作的只是將再也不使用的對象設置爲null
函數的返回值:
由return返回
自執行函數:
//自執行寫法1 (function T(){ alert(1) })() //自執行寫法2 var T1=function(){ alert(1) }(); //傳值 var para1={a:1;b:2,c:'Ok'} var T1=function(obj){ alert(obj.a) }(para1); //若是不用自執行方式,就得調用 function T(){ alert(1) } T();//調用
數組(Array)
屬性:length,constructor,prototype
-數組也是一個對象
-它和咱們普通對象功能相似,也是用來儲存一些值的
-不一樣的是普通對象是使用字符串做爲屬性名的,而數組是使用數組來做爲索引操做元素
-索引:
從0開始的一個整數就是索引
-數組的存儲性能比普通對象要好,在開發中咱們常常食用數組來存儲一些數據
//建立數組對象
//使用構造函數建立數組時,也能夠同時添加元素,將要添加的元素做爲構造函數的參數傳遞,元素之間用,隔開
var arr=new Array();//var arr=new Array(1,2)
//使用typeof檢查一個數組時,會返回Object,讀取數組中的元素,語法:arr[0],若是讀取不存在的索引,他不會報錯而是返回undefined
使用字面量來建立數組:語法[](使用字面量建立數組時,能夠在建立時就指定數組中的元素
var arr=[];//var arr=[1,2];
-獲取數組的長度(語法:數組.length)
- 修改length:若是修改的length大於原長度,則多出部分會空出來,若是修改length小於原長度,則多出的元素會被刪除
- 向數組的最後一個位置添加元素:(語法:數組[數組.length]=值
- 數組中的元素能夠是任意的數據類型(也能夠是對象,函數)函數也是對象
push():
-該方法能夠向數組的末尾添加一個或多個元素,並返回數組的新長度
-能夠將要添加的元素做爲方法的參數傳遞,這些元素會自動添加到數組的末尾
pop():
-該方法能夠刪除並返回數組的最後一個元素,並將刪除元素做爲返回值返回
unshift():
-向數組的開頭添加一個或多個元素,並返回新的數組長度
-向前面插入元素後,其餘元素索引會依次調整
shift():
-能夠刪除數組的第一個元素,並將刪除的元素做爲返回值返回
Js中提供forEach()方式遍歷數組(兼容ie8以上的瀏覽器)
- 須要函數做爲參數,像這種函數,由咱們建立但不禁咱們調用的,咱們稱爲回調函數,數組有幾個元素,函數就會執行幾回,每次執行時,瀏覽器會將遍歷的元素以實參形式傳遞進來,咱們能夠來定義形參來讀取這些內容
-瀏覽器會在回調函數中傳遞三個參數:
-value:當前正在遍歷的元素
-index:當前正在遍歷的元素的索引
-obj:當前正在遍歷的數組(obj)
slice(start,end)
- 從數組中提取出指定元素,不會改變原數組,而是將截取到的元素封裝到一個新數組中返回
- 參數:start:截取開始位置的索引,包含開始索引
end:截取結束位置的索引,不包含結束索引
(第二個參數能夠不寫,此時會截取從開始索引日後的全部元素)
(索引能夠傳遞一個負值,若是傳遞一個負值,則從後往前計算)-1:倒數第一個;-2:倒數第二個
splice(start,num,args)(刪除,添加,替換)
-能夠用於刪除數組中的指定元素,使用splice()會影響到原數組,會將指定元素從原數組中刪除,並將被刪除的元素做爲返回值返回
-參數:start:開始位置的索引,num:表示刪除的數量,args:能夠傳遞一些新的元素,這些元素將會自動插入到開始位置索引前面
數組去重問題: var arr=[1,2,3,2,1,3,4,2,5]; var arr1=arr.sort(); var res=[]; for(var i=0;i<arr1.length;i++){ if(arr1[i]!==arr1[i+1]){ res.push(arr1[i]); } }
------------------------------------------------
concat()
- 能夠鏈接兩個或多個數組(元素),將新的數組返回,不會對原數組有影響
Join()
- 該方法能夠將數組轉換爲一個字符串,該方法不會對原數組產生影響,而是將轉換後的字符串做爲結果返回,在Join()中能夠指定一個字符串做爲參數,這個字符串會成爲數組中元素的鏈接符,默認爲,
reverse()
-該方法用來反轉數組,會直接修改原數組
sort()
- 能夠用來對數組中的元素排序,會修改原數組,默認會按照Unicode編碼排序
(即便對於純數字的數組,使用sort()排序時,也會按照Unicode編碼來排序,因此對於數字進行排序時,可能會獲得錯誤的結果,咱們能夠本身來指定排序的規則)
- 咱們能夠在sort()添加一個回調函數,來指定排序規則,回調函數中須要定義兩個形參,瀏覽器將會分別使用數組中的元素做爲實參去調用回調函數,使用哪一個元素不肯定,但確定是在數組中a必定在b前面
-瀏覽器根據回調函數的返回值決定元素的順序
若返回一個大於0的值,則元素會交換,若返回一個小於0的數,則元素位置不變,若返回等於0,則認爲兩個元素相等,也不交換位置
var arr=[5,7.2,3,1]; arr.sort(function(a,b){//升序排列 /* if(a>b) return 1; if(a<b) return -1 if(a=b) return 0;*/
return a-b; }) alert(arr);
call()和apply()
function fun(){
alert('hell');}
fun.apply();
fun.call();
fun()
這三者執行效果同樣
-------------------------------------
function fun(){
alert(this.name);
}
- 這兩個方法都是函數對象的方法,須要經過函數對象來調用
- 當對函數調用call()和apply()都會調用函數執行
- 在調用call()和apply()能夠將一個對象指定爲第一個參數 ,此時這個對象將會成爲函數執行時的tihs
- call()方法能夠將實參在對象以後依次傳遞,apply()方法須要將實參封裝到一個數組裏統一傳遞
arguments
在調用函數時,瀏覽器每次都會傳遞進兩個隱含的參數
- 函數上下文對象 this
- 封裝實參的對象arguments
- arguments是一個類數組對象,它能夠經過索引來操做數據,也能夠獲取長度
- 在調用函數時,咱們所傳遞的實參都會在arguments中保存
- arguments.length能夠用來獲取實參的長度
- 咱們即便不定義形參,也能夠經過arguments來使用實參
只不過比較麻煩
arguments[0]:表示第一個實參
arguments[1]:表示第2個實參
- 它裏面有一個屬性叫作callee
這個屬性對應一個函數對象,就是當前正在指向的函數的對象
function fun(){ console.log(arguments instanceof Array);//false console.log(Array.isArray(arguments));//false }
Date對象
- 在Js中使用Date對象來表示一個時間
建立一個Date對象 若是直接使用 構造函數建立一個Date對象,則會封裝爲當前代碼執行的時間 var d=new Date() console.log(d);//Thu Feb 14 2019 13:35:00 GMT+0800 (中國標準時間) 建立一個指定的時間對象 須要在構造函數中傳遞一個表示時間的字符串做爲參數 日期格式 月/日/年 時:分:秒 var d=new Date('12/03/2016 21:21:30') console.log(d);//Sat Dec 03 2016 21:21:30 GMT+0800 (中國標準時間)
Math
-Math和其餘對象不一樣,它不是一個構造函數
它屬於一個工具類不用建立對象,它裏面封裝了數學運算相關的屬性和方法
好比
Math.PI 表示圓周率
console.log(Math.abs(-1)) //1
console.log(Math.ceil(1.2))//Math.ceil對一個數進行向上取整,小數位只要有值就自動進1
console.log(Math.floor(1.9))//Math.floor對一個數進行向下取整,小數位會被舍掉
console.log(Math.round(1.9))//Math.round對一個數進行四捨五入取整
Math.random() 生成一個0-1之間的隨機數,(不包含0和1)
// 生成一個0-x之間的隨機數
Math.round(Math.random()*x)
//生成一個1-10之間的隨機數
Math.round(Math.random()*9+1)
//生成一個2-10之間的隨機數
Math.round(Math.random()*8+2)
生成一個x-y之間的隨機數(包含x,y)
Math.round(Math.random()*(y-x)+x)
包裝類
基本數據類型:String Number Boolean Null Undefined
引用數據類型:Object
在JS中提供了三個包裝類,經過這個三個包裝類能夠將基本數據類型的數據轉換爲對象
三個包裝類:(瀏覽器底層本身使用)
String():將基本數據類型字符串轉化爲String對象
Number():將基本數據類型的數字轉換爲Number對象
Boolean():將基本數據類型的布爾值轉換爲Boolean對象(對象專程boolean值都是true)
注意:⚠️
- 在實際開發應用中不會使用基本數據的對象,若是使用基本數據類型的對象,在作一些比較時可能會帶來一些不可預期的結果
- 方法和屬性只能添加給對象,不能添加給基本數據類型
當咱們對一些基本數據類型的值去調用屬性和方法時,瀏覽器會臨時使用包裝類將其轉換爲對象,而後再調用屬性和方法
建立一個字符串
- 在底層字符串是以字符數組的形式保存的
var str="Hello world" console.log(str.length);//11 console.log(str[0])//H
length屬性:獲取字符串的長度
charAt():返回字符串中指定位置的字符 根據索引獲取指定的字符
str.charAt(9)//l
charCodeAt():返回字符串中指定位置的字符編碼(Unicode編碼)
fromCharCode():根據字符編碼獲取字符 調用方式:經過String.fromCharCode()調用
concat():用來鏈接兩個或多個字符串
indexOf():用來檢索一個字符串中是否含有指定內容,
-若是字符串中含有該內容,則會返回其第一次出現的索引
-若沒有找到指定的內容,則返回-1
-能夠指定一個第二個參數,用來指定開始查找的位置
lastIndexOf:
該方法的用法和indexOf()同樣,不一樣的是indexOf是從前日後找,而lastIndexOf是從後往前找
-能夠指定一個第二個參數,用來指定開始查找的位置
slice()
- 能夠從字符串中截取指定的內容
- 不會影響原字符串,而是將截取到的內容返回
- 參數:
第一個,開始位置的索引(包括開始位置
第二個,結束位置的索(不包括結束位置)(若是省略第二個參數,則會截取到後面全部
- 也能夠傳遞一個負數做爲參數,負數的話是從後面開始計算(-1:倒數第一個,-2:倒數第二個)
substring()
- 能夠用來截取一個字符串,和slice()相似
- 不一樣的是這個方法不能結束負值,若傳遞了負值,則默認爲0
- 並且還會自動調整參數的位置,若是第二個參數小於第一個,則自動交換
substr()
- 用來截取字符串
- 參數:
1.開始索引的位置
2.第二個爲字符串截取的長度
split():
- 能夠將一個字符串拆分爲一個數組
var str='abc,bcd,efg,def' var result=str.split(','); console.log(result[0]);//result是一個數組,result[0]=abc 逗號就會被捨去
正則表達式:
- 用於定義一些字符串的規則(計算機能夠根據正則表達式,來檢察一個字符串是否符號規則
- 獲取將字符串中符合規則的內容提取出來
/** * 建立正則表達式的對象 語法: var 變量=new RegExp(」正則表達式「,」匹配模式「) 使用typeof檢察正則對象,會返回object
test():檢察一個字符串是否符合正則表達式的規則
若是符合則返回true,不然返回false
在構造函數中能夠傳遞一個匹配模式做爲第二個參數
能夠是:
i 忽略大小寫
g 全局匹配模式 */ var reg=new RegExp('a','i')//檢察字符串中是否含有a console.log(reg);//返回/a/
使用字面量來創造正則表達式(使用字面量來創造正則表達更加簡潔,使用構造函數建立正則表達是更靈活
語法: var 變量=/正則表達式/匹配模式
var reg=new RegExp('a','i')//reg=/a/i
建立一個正則表達式,檢察一個字符串中是否有a或b
reg=/a|b/ //|表示或者
建立一個正則表達式,檢察一個字符串中是否有字母
[]裏面的內容也是或的關係 [ab]===a|b [a-z]表示任意小寫字母
[A-Z]表示任意大寫字母
[A-z]任意字母
檢察一個字符串中是否含有abc或者adc或者aec
reg=/a[bde]c/
[^ ]:除了
split()不管是否指定全局,都會全局匹配
- 能夠將一個字符串拆分爲一個數組
- 方法中能夠傳遞一個正則表達式做爲參數,這樣方法會根據正則表達式去拆分字符串
var str='12a23jg23o4jg45jn6' var result=str.split(/[A-z]/); console.log(result);// ["12", "23", "", "23", "4", "", "45", "", "6"]
search()即便設置全局匹配也沒效果
- 能夠搜索字符串中是否含有指定內容
- 若是搜索到指定內容,則會返回第一次出現的索引,若是沒有搜索到則返回-1
- 它能夠接受一個正則表達式做爲參數,而後會根據正則表達式去檢索字符串
var str='abc aef bac abe abf' var result=str.search(/ab[A-z]/) console.log(result);//0
match()
- 能夠根據正則表達式,從一個字符串中將符合條件的內容提取出來
- 默認狀況下,只會找到第一個符合要求的內容,找到後就會中止檢索
咱們能夠設置正則表達式爲全局匹配模式(能夠爲一個正則表達式設置多個匹配模式,且順序無所謂
- 將匹配的內容封裝到一個數組中返回,即便只查詢到一個結果
replace()
- 能夠將字符串中指定內容替換爲新的內容
-參數:
1.被替換的內容,能夠接受一個正則表達式做爲參數
2.新的內容
- 默認自會替換第一個
var str='12a23jg23o4jg45jn6' var result=str.replace(/[A-z]/gi,''); console.log(result);//1223234456
建立一個正則表達式檢察一個字符串中是否含有aaa
量詞:
- 經過量詞能夠設置一個內容出現的次數
- {n}正好出現n次
- 量詞只對它前面的一個內容起做用
- {m,n}出現m-n次(包含m,n)
- {m,}出現m次以上
- +:表示{1,}
- *:表示{0,}
- ?:{0,1}
檢察一個字符串中是否以a開頭 ^ 表示開頭 $ 表示結尾
若是在正則表達式中同時使用^,$要求字符串必須徹底符合正則表達式
reg=/^a$/ //就是a
建立一個正則表達式,用來檢察一個字符串是不是一個手機號
reg=/^1{3-9}[0-9]{9}$/
. 表示任意字符
邏輯與和邏輯或
1在條件判斷中使用她們
2在賦值操做中,咱們有時也會使用她們
Var A=1||2:首先驗證1是真仍是假,若真,把1賦值給A,若爲假,把2給A
Var A=1&&2:首先驗證1是真仍是假,若真,把2給A,若假,把1給A
Function fn(x)
{//給形式參數賦值默認值:驗證傳遞參數值,若是沒有傳遞實參,其默認值爲零
if(x===undefined)//三個等號,undefined(false,(0)) {x=0} if(typeof x===’undefined’) {x=0} x=x||0(沒有上述嚴謹,if這種是沒傳值,纔會賦值默認值,這種是不傳值或者傳遞的值是假,都讓它等於零) } function fn(callback){ If(typeof callback===‘function’){ Callback();} Callback &&callback();//上面if判斷的簡寫版(不嚴謹):默認callback要否則就傳函數,要否則就不傳 } Fn(function(){})//把一個函數做爲值傳遞給形參,這種機制叫作回調函數
3邏輯與和邏輯或的混合應用模式
(邏輯與的優先級大於邏輯或)
console.log(0||1&&2||0||3&&2||1)//2
4邏輯或的實戰應用:形參賦值默認值(初始化形參)
//es6新語法規範中能夠直接給形參設置默認值
Function fn(x=0){}fn();
//若是x沒有傳遞值(undefined也是沒有傳遞值),默認值是零,一旦傳遞值,無論傳遞的是啥,都是按照傳遞的值處理的
var a=9;
function fn(){
a=0;
return function(b){
return b+a++;}}//函數返回值,就將做用域銷燬,若返回地址則不銷燬
var f=fn ();
console.log(f(5));
console.log(fn()(5));//進入fn函數,而後將5賦值給b
console.log(f(5));
Console.log(a)//5 5 6 2
<body> <input type="button" value="btn1"> <input type="button" value="btn2"> <input type="button" value="btn3"> <script> window.onload=function(){ var oBtn=document.getElementsByTagName('input');//指定標籤名的對象集合 for(var i=0;i<oBtn.length;i++){ oBtn[i].onclick=function(){ alert(i); } } }//循環運行完了,可是btn是點擊的時候才觸發 </script> </body>
緣由:做用域鏈的這種配置機制引出了一個反作用,即閉包只能取得包含函數中任何變量的最後一個值
解決方案: 經過匿名函數強制讓閉包行爲符合預期,以下:
window.onload=function(){ var oBtn=document.getElementsByTagName('input'); for(var i=0;i<oBtn.length;i++){ (function(i){ oBtn[i].onclick=function(){ alert(i); } })(i); } }
或者用Es6中的寫法
window.onload=function(){ var oBtn=document.getElementsByTagName('input');//指定標籤名的對象集合 for(let i=0;i<oBtn.length;i++){ oBtn[i].onclick=function(){ alert(i); } } }
或者直接添加index屬性:
window.onload=function(){ var oBtn=document.getElementsByTagName('input');//指定標籤名的對象集合 for(let i=0;i<oBtn.length;i++){ oBtn[i].index=(i+1); oBtn[i].onclick=function(){ alert(this.index); } } }