簡介:不少概念不清或忘記,從新構建本身的知識體系。天天問本身1~多個問題。我是菜鳥 成爲大神之路!
html
①語法結構建立的對象使用{},[]數組
var o = {name: "Lis",sex:16}; | o 這個對象繼承了Object.prototype上面的全部屬性
|
var arr = ["yo", "whadup", "?"]; | 數組都繼承於 Array.prototype (Array.prototype 中包含 indexOf, forEach等方法)
|
function fun(){ | 函數都繼承於Function.prototype (Function.prototype 中包含 call, bind等方法)
return 2; |
} |
複製代碼
②構造器建立的對象使用new
在 JavaScript 中,構造器其實就是一個普通的函數。當使用 new 操做符 來做用這個函數時,它就能夠被稱爲構造方法(構造函數)bash
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var obj = new Graph();
obj是生成的對象,他的自身屬性有'vertices'和'edges'.
在obj被實例化時,obj.[[Prototype]]指向了Graph.prototype.
複製代碼
③Object.create 建立的對象>>link
ECMAScript 5
中引入了一個新方法。新對象的原型就是調用 create
方法時傳入的第一個參數。app
④class 關鍵字建立的對象
ECMAScript6
引入了一套新的關鍵字用來實現 class
。使用基於類語言的開發人員會對這些結構感到熟悉,但它們是不一樣的。JavaScript
仍然基於原型。這些新的關鍵字包括 class, constructor,static,extends 和 super
。ide
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);
複製代碼
// 定義一個交通工具類
function Vehicle() {
// 屬性
this.name;
this.number;
// 實例方法
this.funBase = function(){
console.log("交通工具名稱:"+this.name+"||"+"可乘坐人數:"+this.number);
}
}
// 原型方法
Vehicle.prototype.funRatio = function(ratio) {
console.log(this.name + ':' + ratio);
};
複製代碼
核心: 將父類的實例做爲子類的原型函數
function Car(){
this.getName = function(){
console.log(this.name);
return this.name;
}
};
function Airplane(){
this.getName = function(){
console.log(this.name);
return this.name;
}
};
Car.prototype = new Vehicle();
Car.prototype.name = '汽車';
Car.prototype.number = '20人';
Airplane.prototype = new Vehicle();
Airplane.prototype.name = '飛機';
Airplane.prototype.number = '100人';
var car = new Car();
var airplane = new Airplane();
//測試
car.funBase();
car.funRatio("60%");
car.getName();
airplane.funBase();
airplane.funRatio("36%");
airplane.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
複製代碼
執行結果: 工具
特色:
* 很是純粹的繼承關係,實例是子類的實例,也是父類的實例
* 父類新增原型方法/原型屬性,子類都能訪問到
* 簡單,易於實現
缺點:
* 要想爲子類新增屬性和方法,必需要在new Animal()這樣的語句以後執行,不能放到構造器中
* 沒法實現多繼承
* 來自原型對象的全部屬性被全部實例共享(來自原型對象的引用屬性是全部實例共享的)(詳細請看附錄代碼: 示例1)
* 建立子類實例時,沒法向父類構造函數傳參
'推薦指數:★★(三、4兩大體命缺陷)'
複製代碼
核心:使用父類的構造函數來加強子類實例,等因而複製父類的實例屬性給子類(沒用到原型)性能
function Car(){
Vehicle.call(this);
this.name = '汽車';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
// 測試
var car = new Car();
car.funBase();
car.funRatio("60%");//TypeError: car.funRatio is not a function[詳細瞭解]
car.getName();
console.log(car instanceof Vehicle); // false
console.log(car instanceof Car); //true
複製代碼
執行結果 測試
特色:
* 解決了1中,子類實例共享父類引用屬性的問題
* 建立子類實例時,能夠向父類傳遞參數
* 能夠實現多繼承(call多個父類對象)
缺點:
* 實例並非父類的實例,只是子類的實例
* 只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法
* 沒法實現函數複用,每一個子類都有父類實例函數的副本,影響性能
'推薦指數:★★(缺點3)'
複製代碼
核心:爲父類實例添加新特性,做爲子類實例返回ui
function Car(){
var vehicle = new Vehicle();
vehicle.name = '汽車';
vehicle.number = '20人';
vehicle.getName = function(){
console.log(vehicle.name);
return vehicle.name;
}
return vehicle;
}
// 測試
var car = new Car();
car.funBase();
car.funRatio("60%");//TypeError: car.funRatio is not a function[詳細瞭解]
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //false
複製代碼
執行結果:
特色:
* 不限制調用方式,無論是new 子類()仍是子類(),返回的對象具備相同的效果
缺點:
* 實例是父類的實例,不是子類的實例
* 不支持多繼承
'推薦指數:★★'
複製代碼
核心:逐一複製父類實例的屬性方法給子類實例
function Car(){
var vehicle = new Vehicle();
for(var p in vehicle){
Car.prototype[p] = vehicle[p];
}
this.getName = function(){
console.log(this.name);
return this.name;
}
}
// 測試
Car.prototype.name = '汽車';
Car.prototype.number = '20人';
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); //false
console.log(car instanceof Car); //true
複製代碼
執行結果:
特色:
* 支持多繼承
缺點:
* 效率較低,內存佔用高(由於要拷貝父類的屬性)
* 沒法獲取父類不可枚舉的方法(不可枚舉方法,不能使用for in 訪問到)
'推薦指數:★(缺點1)'
複製代碼
核心:經過調用父類構造,繼承父類的屬性並保留傳參的優勢,而後經過將父類實例做爲子類原型,實現函數複用
function Car(){
Vehicle.call(this);
this.name = '汽車';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;//組合繼承也是須要修復構造函數指向
// 測試
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
複製代碼
執行結果:
特色:
* 彌補了方式2的缺陷,能夠繼承實例屬性/方法,也能夠繼承原型屬性/方法
* 既是子類的實例,也是父類的實例
* 不存在引用屬性共享問題
* 可傳參
* 函數可複用
缺點:
* 調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
'推薦指數:★★★★(僅僅多消耗了一點內存)'
複製代碼
核心:經過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
function Car(){
Vehicle.call(this);
this.name = '汽車';
this.number = '20人';
this.getName = function(){
console.log(this.name);
return this.name;
}
}
(function(){
// 建立一個沒有實例方法的類
var Super = function(){};
//設置原型
Super.prototype = Vehicle.prototype;
//將實例做爲子類的原型
Car.prototype = new Super();
// 須要修復下構造函數
Car.prototype.constructor = Car;
})();
// 測試
var car = new Car();
car.funBase();
car.funRatio("60%");
car.getName();
console.log(car instanceof Vehicle); // true
console.log(car instanceof Car); //true
複製代碼
執行結果:
特色:
* 堪稱完美
缺點:
* 實現較爲複雜
'推薦指數:★★★★(實現複雜,扣掉一顆星)'
複製代碼
(相關apply()、bind()方法的使用)
①call()、apply()、bind() 都是用來重定義 this 這個對象的!
②參數:
* call的參數是直接放進去的,第二第三第n個參數全都用逗號分隔,直接放到後面 obj.myFun.call(db,'成都', ... ,'string' );
* apply的全部參數都必須放在一個數組裏面傳進去 obj.myFun.apply(db,['成都', ..., 'string' ]);
*
③方法:
* apply:調用一個對象的一個方法,用另外一個對象替換當前對象。例如:B.apply(A, arguments);即A對象'應用'B對象的方法。
* call:調用一個對象的一個方法,用另外一個對象替換當前對象。例如:B.call(A, args1,args2);即A對象'調用'B對象的方法。
複製代碼
參考文章:
① www.cnblogs.com/humin/p/455…
② www.cnblogs.com/lengyuehuah…