
Javascript中定義函數的三種方式,通過執行個體來說明吧。
<script>
//method1
function fn() {
console.log('fn created ');
}
//method2
var fn2 = function () {
console.log('fn2 created');
}
//method3
var fn3 = new Function('test', 'console.log(test);');
fn3('fn3 test');
console.dir(fn3);
console.log(fn3 instanceof Object);
</script>
運作上面例子,證明了函數也是對象。可以采用new + 構造函數的方式建立執行個體,第三種方式執行效率低。
函數的原型鍊
從結果可以看到Function原型對象的__proto__指向Object。
js中函數的分類和調用方式。
通過執行個體來說明吧。
<script>
//函數的分類和調用方式
//方式1 普通标準函數,this 指向window
function fn() {
console.log('fn1'+ this);
}
fn(); //本質是window.fn(); 全局函數是window的成員
//方式2 對象的方法 this 指向調用者o
var o = {
sayHi: function () {
console.log('fn2'+this);
}
}
o.sayHi();
//方式3 構造函數 this指向新建立的對象,這裡指向star1
function Star(username){
this.username = username;
}
var star1 = new Star('ldh');
//方式4 綁定事件函數 this 指向函數的調用者 btn
var fn = function (){
console.log('btn 被點選了'+ this);
}
btn.onclick = fn;
//點選了按鈕就可以調用函數
//方式5 定時器函數 定時器實際是window成員 是以this 就是window
setInterval(function(){},1000);
//定時器按照設定的時間間隔去調用
//方式6 立即執行函數 this 是window 同方式一
(function(){console.log('function executed')})();
//不需要調用立即執行
</script>
通過上面的例子,基本上歸納了筆者了解的函數使用方式。通過方式4和方式6的對比,
我們可以知道函數後面加了() 表示立即調用,沒加(),表示函數的指針,隻是指明函數不調用函數。
this 指向問題,牢記this指向調用者
改變this 指向的三個函數
this 指向是JS中很重要的問題,在上面的函數分類中,已經有了系統的分析。下面重點總結改變this 指向的三個函數。
call
把父類執行個體改成子類執行個體 實作屬性繼承。
<script>
//call function
function Father(username, age) {
this.username = username;
this.age = age;
}
function Son(username, age, gender) {
Father.call(this, username, age);//實作繼承父類的屬性
this.gender = gender;
}
</script>
apply
apply 和call 不同點,參數是數組(僞數組)。在apply内部會把數組拆成元素
主要使用 借助Math對象,Math.max.apply(Math, [4324, 45, 342, 23])
<script>
//apply function
var o = {
username: 'testuser'
};
function fn(arr) {
console.log(arr);
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
console.log(this);
}
fn.apply(o, [23, 43]);
console.log(Math.max(43, 45, 243, 342));
console.log(Math.max.apply(Math, [4324, 45, 342, 23]));
</script>
bind
隻改變this 的指向 不調用函數。
<body>
<button>click me</button>
<button>click me</button>
<button>click me</button>
<script>
//bind function
//案例:實作多個按鈕發送驗證碼後 3s 可以再次發送
var btns = document.querySelectorAll('button');
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
this.disabled = true;
setTimeout(function () {
this.disabled = false;//改變this 指向btn ,3000ms 後執行
}.bind(this), 3000);
}
}
</script>
</body>