[TOC]
## 構造函數
所有引用類型都有構造函數
```
//構造函數一般以大寫字母開頭.所以一般判斷是否是構造函數,可以通過首字母大寫判斷.
function Foo(name, age){
this.name= name
this.age= age
this.class = ' class-1'
// return this//默認有這一行
}
var f= new Foo('zhangsan, 20);
//varf1= new Foo(Lisi,22); //創建多個對象
```
## 構造函數-擴展
```
var a={} //其實是vara= new Object0的語法糖
var a=[] //其實是vara= new Array的語法糖
function Foo{} //其實是 var foc= new Function()
```
> 使用 instanceof判斷一個函數是否是一個變量的構造函數
## 原型規則和示例
- 所有的引用類型(數組、對象、函數),都具有對象特性,即可自由擴展屬性(除了"null"意外)
```js
//什么是可自由擴展屬性
var obj= {}; obj.a= 100;
var arr=[]; arr.a= 100;
function fn(){}; fn.a=100;
```
- 所有的引用類型(數組、對象、函數),都有一個`__proto__`(隱式原型)屬性,屬性值是一個普通的對象
```
console. Log(ob]._proto__)
console. log(arr._proto__)
console. log (fn.__proto__)
```
- 所有的**函數**,都有一個 `prototype`(顯示原型)屬性,屬性值也是一個普通的對象
```js
console.log(fn.prototype)
```
- 所有的引用類型(數組、對象、函數),`_ proto_`屬性值指向它的構造函數的" prototype“屬性值
```js
console.log(obj.__proto__===Object. prototype ) //對象的__proto__
```
- 當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么會去它的`_ proto_`(即它的構造函數的prototype)中尋找。
```js
//構造函數
function Foo(name, age){
this.name = name;
}
Foo.prototype.alertname= function (){
alert(this.name)
}
//創建示例
var f= new Foo( 'zhangsan')
f.printname= function (){
console.log(this.name)
}
//測試
f.printname()
f.alertname()
```
- 循環對象自身的屬性
```js
var item
for (item in f ){
//高級瀏覽器已經在 for in中屏蔽了來自原型的屬性
//但是這里建議大家還是加上這個判斷,保證程序的健壯性
if (f.hasownProperty(item)){//判斷是否是自身的屬性
console.log(item)
}
}
```
## 原型鏈
```
//構造函數
function Foo(name, age){
this.name = name;
}
Foo.prototype.alertname= function (){
alert(this.name)
}
//創建示例
var f= new Foo( 'zhangsan')
f.printname= function (){
console.log(this.name)
}
//測試
f.printname()
f.alertname()
f.toString() //要去f,_ proto__. __proto__中查找
```

## instanceof
用于判斷引用類型屬于哪個構造函數的方法
```
f.instanceof Foo的判斷邏輯是
f的_ proto_一層一層往上,能否對應到 Foo.prototype
再試著判斷 f instanceof object
```
### 真題
如何準確判斷一個變量是數組類型
```
var arr=[];
arr instanceof Array // true
typeof arr // object, typeof是無法判斷是否是數組的
```