ES6面向對象
js中的面向對象
function User(name, age) { this.name = name; // 定義屬性 this.age = age; } // 通過原型添加方法 User.prototype.showName = function() { console.log(this.name); }; let user = new User('rose', 20); // 實例化 user.showName(); // 調用方法
可以看到js的類和構造函數是沒什么區別
ES6有了個關鍵字:Class,來定義類,和java差不多
class User { constructor(name, age) { // 構造器 this.name = name; this.age = age; } // 定義類方法 showName() { console.log(this.name); } } let user = new User('rose', 21); user.showName();
這個用了ES6寫法的class 和 上面用構造函數定義的類,輸出結果都一樣。
ES6的class 有了專門的構造器 constructor,構造器和類分開了,定義方法:不需要原型來定義了,直接再類里面定義方法。
ES6定義類的寫法
// 匿名類 let Example1 = class { constructor(a) { this.a = a; console.log(a); } } let ex1 = new Example1(1); // 命名類 let Example2 = class Example2 { constructor(a) { this.a = a; console.log(a); } } let ex2 = new Example2(2); // 類聲明 class Example { // class主體內容 constructor(a, b) { this.a = a; this.b = b; } }
注意點:
1、不可重復聲明
2、類定義不會被提升,這意味着,必須在訪問前對類進行定義,否則就會報錯。類中方法不需要 function 關鍵字。
3、方法間不能加分號。
4、class 的實例化必須通過 new 關鍵字。
面向對象的三大特點:封裝、繼承、多態。ES6有了class可以封裝了方法,也有繼承。
js的繼承
function User(name, age) { this.name = name; this.age = age; } User.prototype.showName = function() { console.log(this.name); } let user = new User('rose', 21); //user.showName(); function VipUser(name, age, level) { User.call(this, name, age); // 通過call調用User類 this.level = level; // vipUser對象的屬性 } VipUser.prototype = new User(); // 通過原型實現繼承 VipUser.prototype.constructor = VipUser; VipUser.prototype.showLevel = function() { console.log(this.level); }
let vip = new VipUser('rose', 20 , 10); vip.showName(); // 使用父類的方法 vip.showLevel(); // 使用自己的方法
ES6的繼承:關鍵字:extends 繼承、super 超級
class User { constructor(name, age) { // 構造函數 this.name = name; this.age = age; } // 定義類方法 showName() { console.log(this.name); } } class VipUser extends User { constructor(name, age, level) { super(name, age); // 父類 this.level = level; // 自己的屬性 } showLevel() { console.log(this.level); } } let vip = new VipUser('rose', 22, 2); // 實例化vipUser類 vip.showName(); vip.showLevel(); // 調用方法
Class 中的this指向
class User { constructor(name, age) { //constructor 里面的this this.name = name; this.age = age; } showName() { // 方法里面的this console.log(this.name); } } let user = new User('rose', 10);
1、constructor 構造器里面的this是指向創建的實例對象
let that; class User { constructor(name, age) { //constructor 里面的this this.name = name; this.age = age; that = this; console.log(this); } showName() { // 方法里面的this console.log(this.name); } } // 每次實例化都會調用constructor構造器里面的代碼 let user = new User('rose', 10); // User {name: "rose", age: 10} console.log(that === user); // 構造器的this和實例的對象對比:true
2、方法里面的this
let that; class User { constructor(name, age) { //constructor 里面的this this.name = name; this.age = age; } showName() { // 方法里面的this console.log(this.name); } showThis() { console.log(this); // 方法里面的this // 一般方法里面的this都是指向 誰 調用這個方法就指向 誰 that = this; } } let user = new User('rose', 10); user.showThis(); console.log(that === user); // true
<button id='bottom'>點我</button> <script> let that; class User { constructor(name, age) { //constructor 里面的this this.name = name; this.age = age; this.btn = document.getElementById('bottom'); this.btn.onclick = this.userAge; } showName() { // 方法里面的this console.log(this.name); } showThis() { console.log(this); // 方法里面的this // 一般方法里面的this都是指向 誰 調用這個方法就指向 誰 that = this; } userAge() { // 這個函數里面的this:指向了btn按鈕,因為是按鈕調用了這個函數, console.log(this.age); } } let user = new User('rose', 10); // 點擊頁面按鈕輸出 undefined ,因為按鈕對象沒有定義age屬性 </script>
要點擊按鈕輸出我實例的User的age
<button id='bottom'>點我</button> <script> let that; class User { constructor(name, age) { //constructor 里面的this this.name = name; this.age = age; this.btn = document.getElementById('bottom'); this.btn.onclick = this.userAge; that = this; } showName() { // 方法里面的this console.log(this.name); } showThis() { console.log(this); // 方法里面的this // 一般方法里面的this都是指向 誰 調用這個方法就指向 誰 } userAge() { // that 存儲了構造器里面的this console.log(that.age); } } let user = new User('rose', 10); // 點擊頁面按鈕輸出 10 </script>
通過全局變量that,that === 實例化的對象。