自我介紹:大家好,我是吉帥振的網絡日志;微信公衆号:吉帥振的網絡日志;前端開發工程師,工作4年,去過上海、北京,經曆創業公司,進過大廠,現在鄭州敲代碼。
JS函數專欄
1【JS函數】JS函數之普通、構造、閉包函數
2【JS函數】JS函數之定時器函數
3【JS函數】JS函數之防抖、節流函數
4【JS函數】JS函數之排序函數,對象數組根據某屬性排序
5【JS函數】JS函數之高階函數、組合函數、函數柯裡化
一、普通函數
關于函數基礎内容建議檢視w3school:JavaScript 函數
二、構造函數
1.定義:
構造函數就是初始化一個執行個體對象,對象的prototype屬性是繼承一個執行個體對象
2.主要内容:
a.預設函數首字母大寫
b.構造函數并沒有顯示傳回任何東西。new 操作符會自動建立給定的類型并傳回他們,當調用構造函數時,new會自動建立this對象,且類型就是構造函數類型。
c.也可以在構造函數中顯示調用return.如果傳回的值是一個對象,它會代替新建立的對象執行個體傳回。如果傳回的值是一個原始類型,它會被忽略,新建立的執行個體會被傳回。
function Person( name){
this.name =name;
}
var p1=new Person('John');
等同于:
function person(name ){
Object obj =new Object();
obj.name =name;
return obj;
}
var p1= person("John");
d.因為構造函數也是函數,是以可以直接被調用,但是它的傳回值為undefine,此時構造函數裡面的this對象等于全局this對象。this.name其實就是建立一個全局的變量name。在嚴格模式下,當你補通過new 調用Person構造函數會出現錯誤。

e.也可以在構造函數中用Object.defineProperty()方法來幫助我們初始化:
function Person( name){
Object.defineProperty(this, "name"{
get :function(){
return name;
},
set:function (newName){
name =newName;
},
enumerable :true, //可枚舉,預設為false
configurable:true //可配置
});
}
var p1=new Person('John');
f.在構造函數中使用原型對象
//比直接在構造函數中寫的效率要高的多
Person.prototype.sayName= function(){
console.log(this.name);
};
但是如果方法比較多的話,大多人會采用一種更簡潔的方法:直接使用一個對象字面形式替換原型對象,如下:
Person.prototype ={
sayName :function(){
console.log(this.name);
},
toString :function(){
return "[Person "+ this.name+"]" ;
}
};
這種方式非常流行,因為你不用多次鍵入Person.prototype,但有一個副作用你一定要注意:
使用字面量形式改寫了原型對象改變了構造函數的屬性,是以他指向Object而不是Person。這是因為原型對象具有一個constructor屬性,這是其他對象執行個體所沒有的。當一個函數被建立時,它的prototype屬性也被建立,且該原型對象的constructor屬性指向該函數。當使用對象字面量形式改寫原型對象時,其constructor屬性将被置為泛用對象Object.為了避免這一點,需要在改寫原型對象的時候手動重置constructor,如下:
Person.prototype ={
constructor :Person,
sayName :function(){
console.log(this.name);
},
toString :function(){
return "[Person "+ this.name+"]" ;
}
};
//再次測試:
p1.constructor===Person
//true
p1.constructor===Object
//false
p1 instanceof Person
//true
三、閉包函數
1.定義:
閉包函數指有權通路另一個函數作用域中的變量的函數。在本質上,閉包就是将函數内部和函數外部連接配接起來的橋梁。閉包是一種保護私有變量的機制,在函數執行時形成私有的作用域,保護裡面的私有變量不受外界幹擾。
2.主要内容:
要了解JavaScript閉包,就要先了解JavaScript的變量作用域。
變量的作用域有兩種:全局的和局部的(全局變量和局部變量)
JavaScript中,在函數内部可以直接讀取到全局變量。
var n=10
function fn(){
alert(n)
}
fn() //10
而在函數外部無法讀取到函數内部的變量。
function fn(){
var n=10;
}
fn()
alert(n) //n is not defined 函數外部無法讀取到函數内部的n
注意:函數内部使用var聲明變量的時候,這個變量是局部變量,如果不使用var,那麼這個變量就是一個全局變量。
例如:
function fn(){
n=10;
}
fn()
alert(n) //10
另外,函數的參數也是局部性的,隻在函數内部起作用。
在正常情況下,我們是無法得到函數内部的局部變量的,隻有變通方法才可以——在函數内部再聲明一個函數。
function f1(){
var n=10;
function f2(){
alert(n)
}
}
f2函數可以得到f1函數内的所有局部變量,但是f1函數卻無法得到f2函數内部的局部變量——JavaScript語言特有的“鍊式作用域”結構。(即子對象會一級一級地向上尋找所有父對象的變量),是以,父對象的所有變量,對于子對象都是可見的。
f2函數可以擷取到父級函數f1的局部變量,那麼如果把f2()函數傳回,在函數f1外部就可以通路到f1()函數内部的變量了。
例如:
function f1(){
var n=10;
function f2(){
alert(n)
}
return f2()
}
f1() //頁面彈出10
例子中的f2()函數就是一個閉包函數。
3.用途
(1)可以讀取父級作用域函數内部的變量;
(2)讓變量的值始終儲存在記憶體中(讓局部變量變成全局變量),不被垃圾回收機制清除。