原型和原型鏈

構造函數

//首字母是大寫的函數基本都是構造函數
function Foo(name, age) {
    this.name = name
    this.age = age
    this.class = 'class-1'
    //return this      //默認有這一行,就是如果不添加return this,也會默認返回this
}
var f = new Foo('zhangsan', 20)

步驟:1.傳入參數 2.this變成空對象 3.return this

構造函數-擴展

var a = {} 其實是var a = new Object()的語法糖
var a = []其實是var a = new Array()的語法糖
function Foo(){...}其實是var Foo = new Function(...)
使用instanceof判斷一個函數是否是一個變量的構造函數

判斷一個變量是否為“數組”:變量instanceof Array

原型規則和示例

1.所有的引用類型(數組、函數、對象),都具有對象特性,即可自由擴展屬性(除了“null”以外)

var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn () {}; fn.a = 100;
自由擴展屬性就是都可以添加a屬性,自然也可以添加b,c等其他屬性

2.所有的引用類型(數組、對象、函數,不包括null),都有一個proto屬性,屬性值是一個普通的對象

__proto__ : 隱式原型
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

3.所有函數都有一個prototype屬性,屬性值也是一個普通對象

prototype: 顯式原型
console.log(fn.prototype)

4.所有的引用類型(數組、對象、函數),proto屬性值指向(完全等于)它的構造函數的"prototype"的屬性值

console.log(obj.__proto__ === Object.prototype)

5.當試圖得到一個引用類型的某個屬性時,如果這個對象本身沒有這個屬性,那么會去它的proto(即構造函數的prototype)中尋找

//構造函數
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本身沒有alertName屬性,那么f會去f的隱式原型中尋找,
相當于去f的構造函數Foo的prototype中尋找,Foo的顯式原型已經擴展好了alertName屬性

//this永遠指向f自身,所以兩個結果打印出的都是'zhangsan'

循環對象自身的屬性

var item
for (item in f) {
    //判斷是否是來自f自身的屬性
    if (f.hasOwnProperty(item)) {
        console.log(item)
    }
}

原型鏈

f.toString()       //要去f.__proto__.__proto__中尋找
2107997750.jpg

instanceof

instanceof用于判斷 引用類型 屬于哪個 構造函數 的方法
f instanceof Foo 的判斷邏輯是:
f 的 proto 一層層往上,能否對應到 Foo.prototype
再試著判斷 f instanceof Object

如何準確判斷一個變量是數組類型

instanceof判斷

var arr = []
arr instanceof Array        //true
typeof arr             //object,typeof是無法判斷是否是數組的

寫一個原型鏈繼承的例子

//動物
function Animal() {
    this.eat = function () {
        console.log('animal eat')
    } 
}
//狗
function Dog() {
    this.bark = function() {
         console.log('dog bark')
    }
}
Dog.prototype = new Animal()         //把Dog的顯式原型賦值成一個對象
var hashiqi = new Dog()

描述new一個對象的過程

1.創建一個新對象
2.this指向這個新對象
3.執行代碼,即對this賦值
4.返回this

zepto(或其他框架)源碼中如何使用原型鏈

寫一個封裝DOM查詢的例子

function Elem(id) {
    this.elem = document.getElementById(id)
}
Elem.prototype.html = function (val) {
    var elem = this.elem
    if (val) {
         elem.innerHTML = val
         return this         //鏈式操作
    } else {
         return elem.innerHTML
    }
}
Elem.prototype.on = function (type, fn) {
    var elem = this.elem           //獲取元素
    elem.addEventListener(type, fn)
    return this
}
var div1 = new Elem('question-header')
//console.log('div1.html()')
div1.html('<p>hello imooc</p>')
div1.on('click', function() {
    alert('clicked')
})
//鏈式操作
//在擴展屬性時,結尾返回return this,就可以有鏈式操作
div1.html('<p>hello imooc</p>').on('click', function() {alert('clicked')
}).html('<p>javascript</p>')
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容