構造函數
//首字母是大寫的函數基本都是構造函數
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>')