1. 程式人生 > >js學習筆記02-類和對象,繼承

js學習筆記02-類和對象,繼承

類 繼承

創建類和對象
//1)構造函數定義類,不用new
function Dog(){
 this.name = "Luby";
 this.say = function(){
  console.log("wangwang!");
 }
}
let objDog = new Dog();  //創建對象的時候new
//2)工廠方式定義類
function Dog(){
  let dog = new Object;  //變量,然後new Object;
    dog.name = "Luby";
    dog.say = function(){
      console.log("wangwang");
    }
    return dog;
}
let dog = Dog();  //直接使用函數 
//以上兩種方式的缺點:每一個新的對象都需要創建一個say();
//3)一般用原型+構造函數的方式定義類
function Dog(){
 this.name = "Luby";
}
Dog.prototype.say = function(){
  console.log("wangwang!");
 }
let objDog = new Dog();  //

構造函數

結構語法

//構造函數並不聲明局部變量,而是使用 this 關鍵字來保存數據
//this 是指在構造函數前面使用 new 關鍵字創建的新對象
function SoftwareDeveloper() {
  this.useLanguage = ‘JavaScript‘;
}
let developer = new SoftwareDeveloper();

查看對象的構造函數 (instanceof)

function SoftwareDeveloper() {
  this.useLanguage = ‘JavaScript‘;
}
let developer = new SoftwareDeveloper();
developer instanceof SoftwareDeveloper; // instanceof返回值為true;

constructor 屬性

每次創建一個對象時,都會有一個特殊的屬性被暗中分配給它:constructor。訪問一個對象的 constructor 屬性會返回一個對創建該對象的構造函數的引用!

function Cat(){
 this.name = "fish";
}
let obj = new Cat();
console.log(obj.constructor); //  ? Cat(){this.name = "fish";)

如果某個對象是使用字面量表示法創建的,那麽它的構造函數就是內置的 Object() 構造函數!

let obj = {
 name: "fish"
}
console.log(obj.constructor);//  ? Object() { [native code] } 
// 和java的class一樣(每個class都有一個無參的什麽都不做得構造函數)

this

當使用 new 運算符來調用構造函數時,this 變量會被設置為新創建的對象。當在對象上調用方法時,this 會被設置為該對象本身。當在瀏覽器環境中調用函數時,this 會被設置為 window,也被稱為全局對象。

總結:

函數如何調用決定了函數內this的值(當前的函數屬於誰或當前發生事件的對象)
構造函數中的this 是指在構造函數前面使用 new 關鍵字創建的新對象

this的應用: call(),apply(),bind()(回調函數)

call() 是一個直接調用到函數上的方法。我們傳遞給它一個單一的值,以設置為 this 的值,然後逐個傳入該函數的任何參數,用逗號分隔。
apply()區別就是後面的多個參數為數組,事先並不知道函數所需要的參數個數就使用apply

const num = {
  sum: function (n1,n2) {
    return n1*n2;
  }
};
const title = {
  n1: 25,
  n2: 18.0
}
console.log(num.sum.call(title,title.n1,title.n2));//450  相當於把.call前面的方法聲明到obj這個對象裏面
console.log(num.sum.apply(title,[title.n1,title.n2]));

使用 bind() 來保存 this(回調函數中的this)

const dog = {
 age: 3,
 growOneYear: function(){
 this.age +=1;
}
}
function invokeTwice(cb) {
 cb();
 cb();
}
invokeTwice(dog.growOneYear);//這裏的this為window
console.log(dog.age); //3
let change = dog.growOneYear.bind(dog);
invokeTwice(change); //由bind指定了this為dog
console.log(dog.age); //5

window 對象

頁面的 URL (window.location;)
頁面的垂直滾動位置 (window.scrollY)
滾動到新位置(window.scroll(0, window.scrollY + 200);,從當前位置向下滾動 200 個像素)
打開一個新的網頁 (window.open("https://www.sugarbeans.com/");)

對象 Object

var goods = new Object();
Object.keys(goods);
Object.values(goods);

原型繼承prototype

JavaScript 中的繼承是指一個對象基於另一個對象
JavaScript 中的繼承重點就是建立原型鏈
當使用 new 運算符將一個函數作為構造函數來調用時,該函數會創建並返回一個新的對象。這個對象會被秘密鏈接到其構造函數的 prototype,而它只是另一個對象。使用這個秘密鏈接,可以讓一個對象訪問原型的屬性和方法,就像是它自己的一樣。如果 JavaScript 沒有在某個對象中找到一個特定屬性,它將在原型鏈上繼續查找。如有必要,它會一路查找到 Object()(頂級父對象)
proto(註意每一端有兩個下劃線)是構造函數所創建的所有對象(即實例)的一個屬性,並直接指向該構造函數的 prototype 對象(警告:不要使用這個屬性)
簡單應用

function Cat(){
this.name = "coff";
}
let cat1 = new Cat();
let cat2 = new Cat();
Cat.prototype.say = function(){
  console.log("woool");
};
Cat.prototype.color = "red" //添加屬性
Cat.prototype = { //指向了新的對象
 color: "red"
};
console.log(cat1.__proto__); //  {say: ?, color: "red", constructor: ?}

Object.create()

防止子對象修改父對象的屬性 如:child.prototype.earBones = 5;
Object.create() 會接受一個對象作為參數,並返回一個新的對象,其 proto 屬性會被設置為傳遞給它的參數。然後,你只需要將所返回的對象設置為子對象構造函數的原型即可

const mammal = {
   vertebrate: true,
   earBones: 3
};
const rabbit = Object.create(mammal); //Object.create()
console.log(rabbit);  // {}
console.log(rabbit.__proto__ === mammal); //true

構造函數之間的繼承

function Animal(name){
  this.name = name;
}
Animal.prototype.walk = function(){
  console.log(`${this.name} walks!`);
} //定義了類Animal
function Cat(name){
  Animal.apply(this,[name]); //不使用new,使用父類的屬性,如下:
     //let obj = new Animal(name);
 // this.name = obj.name;
}
Cat.prototype = Object.create(Animal.prototype); //類Cat繼承Animal
let str = new Cat("miaomiao");
console.log(str.walk());

原型相關的函數

hasOwnProperty
hasOwnProperty() 可以幫助你找到某個特定屬性的來源。在向其傳入你要查找的屬性名稱的字符串後,該方法會返回一個布爾值,指示該屬性是否屬於該對象本身(即該屬性不是被繼承的)

function Phone() {
   this.operatingSystem = ‘Android‘;
}
Phone.prototype.screenSize = 6;
const myPhone = new Phone();
const own = myPhone.hasOwnProperty(‘operatingSystem‘); // true
const inherited = myPhone.hasOwnProperty(‘screenSize‘); // false

isPrototypeOf()和Object.getPrototypeOf()
isPrototypeOf()可以檢查某個對象是否存在於另一個對象的原型鏈中。
Object.getPrototypeOf()確定某個對象的原型是什麽呢

const dog = {
 name: "hero",
 age: 2
}
function Cat(){
  this.say= function(){
  console.log("miaomiao") 
};
};
Cat.prototype = dog;  //
let str = new Cat();
//str.say();方法已經被覆蓋
dog.isPrototypeOf(str); //true 註意調用順序.
const myPrototype = Object.getPrototypeOf(str); //獲取原型
console.log(myPrototype); //{name: "hero", age: 2}

js學習筆記02-類和對象,繼承