Q&A:
1. 繼承有什么作用?
- 概念:繼承是指一個對象直接使用另一個對象的屬性和方法掷匠。
- 作用:繼承劃分了類的層次性,父類代表的是更一般珊拼、更泛化的類恳守,而子類則是更為具體考婴、更為細化;繼承是實現(xiàn)代碼重用催烘、擴展軟件功能的重要手段沥阱,子類中與父類完全相同的屬性和方法不必重寫,只需寫出新增或改寫的內(nèi)容伊群,這就是說子類可以復用父類的內(nèi)容考杉,不必一切從零開始。
2. 有幾種常見創(chuàng)建對象的方式? 舉例說明?
- 單一接口創(chuàng)建(Object構(gòu)造函數(shù)或字面量創(chuàng)建):
var obj1 = new Object();
var obj2 = {};
單一接口創(chuàng)建對象
- 工廠模式(函數(shù)封裝單一接口創(chuàng)建對象的細節(jié)):
function createPerson(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sayName = function() {
console.log(this.name);
};
return obj;
}
var p1 = createPerson('kevin', 24);
var p2 = createPerson('zhao', 23);
工廠模式
通過在函數(shù)中創(chuàng)建一個新對象舰始,將具體細節(jié)添加到新對象崇棠,最后返回出新對象的過程,解決單一接口創(chuàng)建對象的大量重復代碼丸卷,但是仍有很多問題枕稀,因此有后面介紹的新模式出現(xiàn)。
- 構(gòu)造函數(shù)模式(形式類似原生構(gòu)造函數(shù)的自定義構(gòu)造函數(shù)):
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
console.log(this.name);
};
}
var p1 = new Person('kevin', 24);
var p2 = new Person('zhao', 23);
構(gòu)造函數(shù)模式
構(gòu)造函數(shù)模式相比于工廠模式谜嫉,能夠解決對象識別的問題(知道一個對象的類型)萎坷,但是每個實例中的方法是不一樣的,每個sayName()相當于new Function()創(chuàng)建的新方法沐兰,這樣完全沒必要哆档,所以下面介紹原型模式。
- 原型模式:
function Person() {}
Person.prototype.name = 'kevin';
Person.prototype.age = 24;
Person.prototype.sayName = function() {
console.log(this.name);
};
var p1 = new Person();
p1.sayName(); // 'kevin'
var p2 = new Person();
p2.sayName(); // 'kevin'
原型模式
原型模式解決了屬性和方法共享的問題住闯,但是也正因為共享瓜浸,使得引用類型屬性容易出現(xiàn)問題,在例子中比原,若name是一個數(shù)組對象屬性插佛,則p1中使用push添加數(shù)組項則在p2中的數(shù)組也跟著改變,所以有了下面的方法量窘。
- 組合使用構(gòu)造函數(shù)模式和原型模式:
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ['john', 'hunger'];
}
Person.prototype.sayName = function() {
console.log(this.name);
}
var p1 = new Person('kevin', 24);
var p2 = new Person('zhao', 23);
混合模式
這種方法雇寇,每個實例都擁有自己的屬性,即使在p2中更改name屬性也不會影響p1的屬性,而方法則添加在原型中谢床,實現(xiàn)共用方法,這種混成的模式取得了兩者的優(yōu)點厘线,是目前認同度最高的一種創(chuàng)建自定義類型的方法识腿。
3. 下面兩種寫法有什么區(qū)別?
<script>
//方法1
function People(name, sex) {
this.name = name;
this.sex = sex;
this.printName = function() {
console.log(this.name);
}
}
var p1 = new People('饑人谷', 2);
//方法2
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function() {
console.log(this.name);
}
var p2 = new Person('若愚', 27);
</script>
- 第一種方法是上面所講的構(gòu)造函數(shù)模式,每創(chuàng)建一個實例造壮,其中的printName()方法就會通過new Function()創(chuàng)建一次渡讼,所以每個實例擁有一個新方法,這是種資源的浪費耳璧;
- 第二種方法是混合模式成箫,將屬性設(shè)置在構(gòu)造函數(shù)中,而將需要共用的方法綁定在原型上旨枯,相比于第一種模式蹬昌,這種模式更加實用。
4. Object.create有什么作用攀隔?兼容性如何皂贩?如何使用?
-
Object.create作用:
Object.create()方法創(chuàng)建一個擁有指定原型和若干個指定屬性的對象昆汹。 -
兼容性:
Object.create是ES5引入的方法明刷,在IE9中嚴格模式不適用,在其他瀏覽器部分版本满粗,parseInt方法配合使用上會出現(xiàn)問題(忽略前導0)辈末,不過主流PC瀏覽器兼容性良好。
Object.create兼容性 - 使用:
function Person() {} //創(chuàng)建空構(gòu)造函數(shù)
Person.prototype.name = 'kevin'; //原型綁定屬性
var p1 = Object.create(Person.prototype); // 創(chuàng)建只繼承原型的實例
var p2 = Object.create(Person.prototype, { //創(chuàng)建繼承原型映皆,同時含有自身屬性的實例
age: {
value: 24
},
name: {
value: 'zhao'
}
});
Object.create使用
5. hasOwnProperty有什么作用挤聘? 如何使用?
- 作用:判斷一個對象是否包含自定義屬性而不是原型上的屬性劫扒;
-
使用:
還是按照上一個問題的例子:
hasOwnProperty
6. 實現(xiàn)Object.create的 polyfill檬洞,如:(ps: 寫個 函數(shù)create,實現(xiàn) Object.create 的功能)
// 第一步:判斷瀏覽器是否支持Object.create
if(typeof Object.create != 'function') {
// 第二步:若不支持Object.create沟饥,則創(chuàng)建Polyfill
Object.create = (function() {
function Temp = () {} // 創(chuàng)建臨時保存原型的函數(shù)
var hasOwn = Object.prototype.hasOwnProperty; // 保存hasOwnProperty方法添怔,方便之后使用
return function(o) {
if(typeof o != 'object') { // 判斷第一個原型參數(shù)類型
throw TypeError('原型參數(shù)必須是一個對象或者null');
} else {
Temp.prototype = o; // 將原型綁定在臨時對象上
var obj = new Temp(); // 創(chuàng)建要返回的新對象
o = null; // 清空雜散參數(shù)對象
if(arguments.length > 1) { // 判斷是否含有第二個屬性參數(shù)
var Properties = Object(arguments[1]); // 創(chuàng)建含有這些屬性的對象
for(var prop in Properties) { // 遍歷對象中的屬性
if(hasOwn.call(Properties, prop)) { // 將對象自身描述符綁定的屬性篩選
obj[prop] = obj[prop]; // 綁定在obj上
}
}
}
return obj; // 返回obj
}
};
})();
}
7. 如下代碼中call的作用是什么?
<script>
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
function Male(name, sex, age) {
Person.call(this, name, sex);
this.age = age;
}
</script>
- 作用:在Male函數(shù)中,調(diào)用Person函數(shù)贤旷,使Male函數(shù)能夠執(zhí)行Person上的初始化代碼广料,實現(xiàn)構(gòu)造函數(shù)繼承。
8. 補全代碼幼驶,實現(xiàn)繼承
function Person(name, sex) {
// todo...
}
Person.prototype.getName = function() {
//todo...
};
function Male(name, sex, age) {
//todo...
}
//todo...
Male.prototype.getAge = function() {
//todo...
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
- 實現(xiàn)繼承:
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function() {
console.log(this.name);
};
function Male(name, sex, age) {
Person.call(this, name, sex);
this.age = age;
}
// 寄生方法:
// function inheritPrototype(subType, superType) {
// function F() {}
// F.prototype = superType.prototype;
// var prototype = new F();
// prototype.constructor = subType;
// subType.prototype = prototype;
// }
//
// inheritPrototype(Male, Person);
// Object.create方法
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male;
Male.prototype.getAge = function() {
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
繼承
Coding:
1. 實現(xiàn)如下dialog 彈窗功能
//功能描述:
// 1. 可使用 dialog.open() 去打開彈窗
// 2. 當點擊確定分蓖、取消時可使用用戶自定義事件
// 3. dialog 可拖動
// 4. 允許頁面展示多個 dialog
function Dialog() {
//todo...
}
var tpl = '<ul><li>列表1</li><li>列表2</li><li>列表1</li><li>列表1</li></ul>';
$('#open4').on('click', function() {
var dialog4 = new Dialog();
dialog4.open({
title: '歡迎來到饑人谷',
message: tpl,
isShowCloseBtn: true,
isShowConfirmBtn: true,
onClose: function() {
alert('close');
},
onConfirm: function() {
alert('確定');
}
});
});
2. 實現(xiàn)如下一個日歷組件
<input class="date-ipt" type="text" placeholder="有初始值" date-init="2016/05/31" />
<input class="date-ipt" type="text" placeholder="無初始值" />
<script>
// 使用
$('.date-ipt').datePicker();
</script>
本文歸本人和饑人谷所有,如需轉(zhuǎn)載請注明出處