對象、原型

1、 OOP 指什么?有哪些特性

OOP是Object-oriented programming的縮寫,指面向對象程序設計。
在面向對象程序設計中有兩個重要概念

  1. 類:
    類是對現實生活中一類具有共同特征的事物的抽象。

  2. 對象:
    對象是類的實例,對象包含屬性和方法,屬性是需要記憶的信息,方法是對象能夠提供的服務。

特性

  1. 繼承
    子類能繼承父類的屬性和方法
    子類能添加新的屬性和方法,還能重寫父類的屬性和方法

  2. 封裝
    隱藏對象的屬性和實現細節,僅對外公開接口

  3. 多態
    指同一個實體同時具有多種形式,同一操作作用于不同對象,可以有不同的解釋,產生不同的執行結果。

2: 如何通過構造函數的方式創建一個擁有屬性和方法的對象?

2.1 構造函數

面向對象編程的第一步,就是要生成對象。

對象是單個實物的抽象。通常需要一個模板,表示某一類實物的共同特征,然后對象根據這個模板生成。

典型的面向對象編程語言(比如 C++ 和 Java),存在“類”(class)這個概念。所謂“類”就是對象的模板,對象就是“類”的實例。但是,JavaScript 語言的對象體系,不是基于“類”的,而是基于構造函數(constructor)和原型鏈(prototype)

JavaScript 語言使用構造函數(constructor)作為對象的模板。所謂”構造函數”,就是專門用來生成對象的函數。它提供模板,描述對象的基本結構。一個構造函數,可以生成多個對象,這些對象都有相同的結構。

構造函數的寫法就是一個普通的函數,但是有自己的特征和用法。

var Vehicle = function () {
  this.price = 1000;
};

上面代碼中,Vehicle就是構造函數,它提供模板,用來生成實例對象。為了與普通函數區別,構造函數名字的第一個字母通常大寫。

構造函數的特點有兩個。

  1. 函數體內部使用了this關鍵字,代表了所要生成的對象實例。

  2. 生成對象的時候,必需用new命令,調用Vehicle函數。

2.2 new 命令的原理

new命令的作用,就是執行構造函數,返回一個實例對象。

new運算符創建對象實例:new后面跟一個函數 F ,根據需要函數可以傳入參數,new F(arguments...)

使用new運算符創建對象實例這一過程分為四步:

  1. 創建一個空對象,作為將要返回的對象實例

  2. 將這個空對象的原型,指向構造函數的prototype屬性

  3. 將這個空對象賦值給函數內部的this關鍵字

  4. 開始執行構造函數內部的代碼(為實例對象添加屬性和方法)

也就是說,構造函數內部,this指的是一個新生成的空對象,所有針對this的操作,都會發生在這個空對象上。構造函數之所以叫“構造函數”,就是說這個函數的目的,就是操作一個空對象(即this對象),將其“構造”為需要的樣子。

如果構造函數內部有return語句,而且return后面跟著一個對象,new命令會返回return語句指定的對象;否則,就會不管return語句,返回this對象。

var Vehicle = function () {
  this.price = 1000;
  return 1000;
};

(new Vehicle()) === 1000
// false

上面代碼中,構造函數Vehicle的return語句返回一個數值。這時,new命令就會忽略這個return語句,返回“構造”后的this對象。

但是,如果return語句返回的是一個跟this無關的新對象,new命令會返回這個新對象,而不是this對象。這一點需要特別引起注意。

var Vehicle = function (){
  this.price = 1000;
  return { price: 2000 };
};

(new Vehicle()).price
// 2000

上面代碼中,構造函數Vehicle的return語句,返回的是一個新對象。new命令會返回這個對象,而不是this對象。

另一方面,如果對普通函數(內部沒有this關鍵字的函數)使用new命令,則會返回一個空對象。

function getMessage() {
  return 'this is a message';
}

var msg = new getMessage();

msg // {}
typeof msg // "object"

上面代碼中,getMessage是一個普通函數,返回一個字符串。對它使用new命令,會得到一個空對象。這是因為new命令總是返回一個對象,要么是實例對象,要么是return語句指定的對象。本例中,return語句返回的是字符串,所以new命令就忽略了該語句。

如果忘了使用new命令,直接調用構造函數會發生什么事?

這種情況下,構造函數就變成了普通函數,并不會生成實例對象this這時代表全局對象,將造成一些意想不到的結果。

var Vehicle = function (){
  this.price = 1000;
};

var v = Vehicle();
v.price
// Uncaught TypeError: Cannot read property 'price' of undefined

price
// 1000

上面代碼中,調用Vehicle構造函數時,忘了加上new命令。結果,price屬性變成了全局變量,而變量v變成了undefined。

通過構造函數的方式創建一個擁有屬性和方法的對象:

function People(name,color){
  this.name=name;
  this.color=color;
  this.sayname=function(){
    console.log(this.name);
  }
}
var person1=new People('xuguojun','red')

3: prototype 是什么?有什么特性

我們創建的每個函數都有一個 prototype(原型)屬性。使用原型的好處是可以讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構造函數中定義對象實例的信息,而是可以將這些信息直接添加到原型中,如下面的例子所示。

function Person(){}

Person.prototype.name = "Stone";
Person.prototype.age = 28;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    console.log(this.name);
};

var person1 = new Person();
person1.sayName();   // "Stone"

var person2 = new Person();
person2.sayName();   // "Stone"

console.log(person1.sayName == person2.sayName);  // true

再來看一幅圖:

image.png

通過圖示我們可以看出一些端倪,實例可以通過prop訪問到其類型的prototype屬性,這就意味著類的prototype對象可以作為一個公共容器,供所有實例訪問。

4:畫出如下代碼的原型圖

function People (name){
  this.name = name;
  this.sayName = function(){
    console.log('my name is:' + this.name);
  }
}

People.prototype.walk = function(){
  console.log(this.name + ' is walking');  
}

var p1 = new People('徐國軍');
var p2 = new People('前端');
Paste_Image.png

5. 創建一個 Car 對象,擁有屬性name、color、status;擁有方法run,stop,getStatus

function Car(name,color,status){
  this.name = name;
  this.color = color;
  this.status = status;
}
Car.prototype.run = function(){
  console.log('running');
};
Car.prototype.stop = function(){
  console.log('stop');
};
Car.prototype.getStatus = function(){
  console.log(this.status);
};

var newCar = new Car('蘭博基尼','black',0);
newCar.run();
newCar.stop();
newCar.getStatus();

6: 創建一個 GoTop 對象,當 new 一個 GotTop 對象則會在頁面上創建一個回到頂部的元素,點擊頁面滾動到頂部。擁有以下屬性和方法

    1. ct屬性,GoTop 對應的 DOM 元素的容器
    1. target屬性, GoTop 對應的 DOM 元素
    1. bindEvent 方法, 用于綁定事件
  • 4 createNode 方法, 用于在容器內創建節點
<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style id="jsbin-css">
    .goTop{
      border: 1px solid yellow;
      width: 110px;
      height: 40px;
      line-height: 40px;
      text-align: center;
      background: yellow;
      cursor: pointer;
      position: fixed;
      bottom: 20px;
      right: 20px;
     }  
  </style>
</head>
<body>
   <div class="ct">
          <p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p>
   </div>
   <script>
      function GoTop($ele){
        this.ct=$ele;
        this.target=$('<div class="goTop">回到頂部</div>');
        this.init();
      };
      GoTop.prototype={
        init:function(){ 
        this.createNode();
        this.bindEvent();
      },
      createNode:function(){
        var me=this;
        me.target.hide();
        $('body').append(me.target);
        $(window).on('scroll',function(){
          if($(window).scrollTop()>300){
            me.target.show();
          }else{
            me.target.hide();
          }
        }); 
       },
      bindEvent:function(){
        var me=this;
        me.target.on('click',function(){
          $(window).scrollTop(0);
        })
      }
    }
    var go=new GoTop( $('body') );
  </script>
</body>
</html>

效果展示

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 使用同一個接口創建很多對象,會產生大量的重復代碼。為解決這個問題嗎,人們開始使用工廠模式的一種變體。 工廠模式 工...
    BertFu閱讀 917評論 0 4
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 朋友圈里各種去過的地方,其實就是變著法兒的"到此一游"
    劉悠茸閱讀 226評論 0 0
  • 時令已經快到了驚蟄,對于禿鷲來說,這個時節本應該是遷徙的時節。但對于鄴城的這些禿鷲而言,寒冷,似乎并沒有成為驅趕它...
    若少兮閱讀 547評論 2 1
  • 很多我們想做的事情和想去的地方到最后由于各種理由和借口而沒有去做不是因為不愛而是因為太向往而生出幾分畏懼
    J夏日secret閱讀 148評論 0 0