1.原型鏈繼承:prototype
var p1 = new Person()
Person.prototype.(method_name) = function() {
// ...
}
Person.prototype.(method_name_2) = function() {
// ...
}
p1.(method_name)()
p1.(method_name_2)()
// 確定就是方法很多的時(shí)候會(huì)造成代碼冗余
2.原型鏈繼承2:prototype
Person.prototype = {
// constructor 重要餐禁!
constructor: Person,
(method_name): function() {
// ...
}
}
var p1 = new Person()
p1.(method_name)()
/** 注意:
1. 一般情況下鱼喉,應(yīng)該先改變?cè)蛯?duì)象狸膏,在創(chuàng)建對(duì)象
2.一般情況下,對(duì)于新原型典阵,會(huì)添加一個(gè)constructor屬性,從而不破壞原有的原型對(duì)象的結(jié)構(gòu)
*/
注意:JavaScript的類繼承其實(shí)本質(zhì)還是用原型繼承來包裝的
3.拷貝繼承(混入繼承)
var p1 = {age: 18}
var p2 = p1;
p2.age = 20;
// 上面代碼p1的age也會(huì)被修改了莱衩,因?yàn)閜1,p2是同一對(duì)象
// 如果想使用某個(gè)對(duì)象中的屬性绰筛,又不能直接修改,就可以創(chuàng)建一個(gè)該對(duì)象的拷貝
// jquery: $.extend: 編寫jquery插件的必經(jīng)之路
// 拷貝繼承(混入繼承)
var p1 = {name: 'T1', age: 18}
// 實(shí)現(xiàn)拷貝繼承
var p2 = {}
for (var key in p1) {
var value = p1[key];
p2[key] = value;
}
p2[age] = 22;
// ...
es6
提供了<對(duì)象擴(kuò)展運(yùn)算符>
var p1 = {name: 'T1', age: 18}
var p2 = {...p1}
// or
var p3 = {...p1, age: 22}
4.原型式繼承
// 場(chǎng)景:
// 創(chuàng)建一個(gè)純潔的對(duì)象
// 創(chuàng)建一個(gè)繼承自某個(gè)父對(duì)象的子對(duì)象
var p1 = {name: 'T1', age: 18}
var p2 = Object.create(p1);
5.借用構(gòu)造函數(shù)繼承
function Person(name, age) {
this.name = name
this.age = age
}
function Student(name, age, sex) {
// 將Person函數(shù)內(nèi)部的this指向Student的實(shí)例
Person.call(this, name, age)
// or (等價(jià)于)
Person.apply(this, [name, age, sex])
this.sex = sex
}
var p1 = new Student('T1', 22, '男')
// ...
// 局限性: Person(父類構(gòu)造函數(shù))的代碼必須完全適用于Student(子類構(gòu)造函數(shù))
6.寄生繼承
7.寄生組合繼承
閉包
1.認(rèn)識(shí)閉包
function fn() {
var a = 5;
return function() {
a++;
console.log(a);
}
}
var f1 = fn();
f1(); // 6
f1(); // 7
f1(); // 8
// 一般認(rèn)為函數(shù)執(zhí)行完畢逐工,變量就會(huì)釋放铡溪,但是此時(shí)由于js引擎發(fā)現(xiàn)匿名函數(shù)要使用a變量,所以a變量并不能得到釋放泪喊,而是把a(bǔ)變量放到匿名函數(shù)可以訪問到的地方去了
// a變量存在于f1函數(shù)可以訪問到的地方棕硫,此時(shí)a變量只能被f1訪問