參考學習:https://www.cnblogs.com/lisha-better/p/5684844.html
1.普通函數調用(window)
2.做爲構造函數調用()
3.做爲方法調用
4.使用call/apply/bind調用
5.ES6箭頭函數調用(this取決於包裹箭頭函數的第一個普通函數)html
**setTimeout()由window對象調用
call()參數爲空,this指向window
匿名函數,this也指向window
web
在事件中,this指向觸發這個事件的對象,特殊的是,IE中的attachEvent中的this老是指向全局對象Windowapp
參考學習:https://www.cnblogs.com/chenwenhao/p/6980401.html
https://www.imooc.com/article/20162
https://www.cnblogs.com/humin/p/4556820.htmlsvg
關於Function和Object建立實例之間的關係
基於原型鏈繼承的鏈圖,對繼承有個具體化的概念: (這個是核心繼承部分)
上圖總體的繼承鏈函數
js繼承:
1.原型鏈繼承
特色;學習
1.要想爲子類新增屬性和方法,必需要在new Animal()這樣的語句以後執行,不能放到構造器中 2.沒法實現多繼承 3.來自原型對象的全部屬性被全部實例共享 4.建立子類實例時,沒法向父類構造函數傳參 function SuperType () { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //繼承SuperType **SubType.prototype = new SuperType();** SubType.prototype.getSubValue = function() { return this.subproperty; } var instance =new SubType(); console.log(instance.getSuperValue()); // true
存在問題:this
1.包含引用類型值的原型屬性會被全部實例共享(修改),而在構造函數中的基本類型和引用類型屬性均不可改變(const附體)
2.建立子類型的實例時,不能向超類的構造函數中傳遞傳遞參數
3.沒法實現多繼承prototype
2.構造函數繼承(在子類型構造函數的內部調用超類型)code
子類型構造函數中向超類型構造函數傳參
問題:函數沒法複用xml
function SuperType() { this.colors = ["red","blue","green"]; } function SubType() { //繼承了SuperType --從新建立SuperType構造函數屬性的副本 SuperType.call(this); } var instance1 = newe SubType(); instance1.colors.push("black"); console.log(instance1.colors); //"red,blue,green,black" var instances2 = new SubType(); console.log(instance2.colors); //"red,blue,green" --完美實現了繼承構造函數屬性
3.組合繼承(避免了原型鏈和構造函數繼承的缺陷)
彌補了方式2的缺陷,能夠繼承實例屬性/方法,也能夠繼承原型屬性/方法
既是子類的實例,也是父類的實例
不存在引用屬性共享問題
可傳參
函數可複用
缺點:
調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { console.log(this.name); }; function SubType(name,age){ //繼承屬性 --從新建立SuperType構造函數屬性的副本 SuperType.call(this,name); this.age = age; } //繼承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function() { console.log(this.age); }; var instance1 =new SubType("Nicholas",29); instance1.colors.push("black"); console.log(instance1.colors); // "red,blue,green,black" instance1.sayName(); // "Nicholas" instance1.sayAge(); // 29 var instance2 = new SubType("Greg",22); console.log(instance2.colors); // "red,blue,green" instance2.sayName(); // "Greg" instance2.sayAge(); // 22
4.實例繼承
特色:
不限制調用方式,無論是new 子類()仍是子類(),返回的對象具備相同的效果
缺點:
實例是父類的實例,不是子類的實例
不支持多繼承
// 定義一個動物類 function Animal (name) { // 屬性 this.name = name || 'Animal'; // 實例方法 this.sleep = function(){ console.log(this.name + '正在睡覺!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); }; function Cat(name){ var instance = new Animal(); instance.name = name || 'Tom'; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false
5.拷貝繼承
特色:
支持多繼承
缺點:
效率較低,內存佔用高(由於要拷貝父類的屬性)
沒法獲取父類不可枚舉的方法(不可枚舉方法,不能使用for in 訪問到)
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
6.寄生組合繼承
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } (function(){ // 建立一個沒有實例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實例做爲子類的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true