js中面向對象(建立對象的幾種方式)

 

一、面向對象編程(OOP)的特色javascript

  抽象:抓住核心問題html

  封裝:只能經過對象來訪問方法java

  繼承:從已有的對象下繼承出新的對象編程

  多態:多對象的不一樣形態windows

 注:本文引用於 http://www.cnblogs.com/yuxingyoucan/p/5797142.html數組


 

1、建立對象的幾種方式app

javascript 建立對象簡單的來講,無非就是使用內置對象或各類自定義對象,固然還可使用JSON,但寫法有不少,也能混合使用。函數

一、工廠方式建立對象:面向對象中的封裝函數(內置對象)性能

function createPerson(name){
   //一、原料
    var obj=new Object();
   //二、加工
    obj.name=name;
    obj.showName=function(){
       alert(this.name);
    }     
    //三、出場
     return obj; 
} 
var p1=createPerson('小米');
p1.showName();

與系統對象的區別:this

    var arr=new Array();//生成一個系統數組對象

    一、系統對象是直接用 new 在外面生成,而工廠定義的是在函數內部生成

    二、工廠定義的函數名稱第一個是小寫開頭,而系統定義的是大寫開頭

工廠模式的優缺點:雖然解決了建立類似對象的問題,可是卻沒有解決對象識別問題(即怎樣知道一個對象的類型)。

二、構造函數建立對象

  當new去調用一個函數,這個時候函數中的this就是建立出來的對象,並且函數的返回值就是this(隱式返回)

  new後面的函數叫作構造函數

  <1>有參數的構造函數

function CreatePerson(name){
  this.name=name;
  this.showName=function(){
    alert(this.name);
  }
}
    var p1=new CreatePerson('小米');

  <2>無參數的構造函數

  function CreatePerson(){}
    var p1=new CreatePerson();
    p1.name="小米";
    p1.showName=function(){
     alert(p1.name);
    }
    p1.showName();

構造函數模式的優缺點:

  一、優勢:建立自定義函數意味着未來能夠將它的實例標識爲一種特定的類型,這是構造函數賽過工廠模式的地方

  二、缺點:每一個方法都要在每一個實例上從新建立一遍

三、對象字面量方式建立對象

person={
  name:"小米",
  age:23
};

四、用原型方式 

  一、原型對象:只要建立了一個新函數,就會爲該函數建立一個prototype屬性,這個屬性指向函數的原型對象。在默認狀況下,全部的原型對象都會自動得到一個constructor(構造函數)屬性,這個屬性是一個指向prototype屬性所在函數的指針

  二、能夠經過isPrototypeOf()方法來肯定對象之間是否存在這種關係

function Person(){}
Person.prototype.name="小米";
Person.prototype.showName=function(){
alert(this.name);
}
var p1=new Person();
p1.showName();

原型模式的優缺點:

  一、優勢:可讓全部的對象實例共享它所包含的屬性和方法

  二、缺點:原型中是全部屬性都是共享的,可是實例通常都是要有本身的單獨屬性的。因此通常不多單獨使用原型模式。

5.混合模型

  構造函數模式定義實例屬性,而原型模式用於定義方法和共享的屬性

function CreatePerson(name){
  this.name=name;
}
  Create.prototype.showName=function(){
    alert(this.name);
  }
    var p1=new CreatePerson('小米');
    p1.showName();
   var p2=new CreatePerson('小米');
    p2.showName();
  alert(p1.showName==p2.showName);//true;緣由:都是在原型下面,在內存中只存在一份,地址相同

  總結:

  function 構造函數(){

    this.屬性;

  }

  構造函數.原型.方法=function(){};

  var 對象1=new 構造函數();

  對象1.方法();

 


 

原型:去改寫對象下面公用的的方法或屬性,讓公用的方法或屬性在內存中存在一份(提升性能)

原型:prototype:要寫在構造函數的下面

var  arr=[];
arr.number=10;
Array.prototype.number=20;
alert(arr.number);//10,
//緣由:普通定義的要比原型定義的權重大,先會找自身的,自身沒有的話再沿着原型鏈找原型上是否有

屬性是否要放在原型下面,就要看該屬性是不是可變的,若是不是可變的,就能夠放在原型下面,用來公用屬性,可變的話放在構造函數下面。

 


 

this的指向問題:在事件或者定時器下比較容易出問題

 


 

 2、包裝對象

一、咱們把系統自帶的對象,叫作系統對象。例如:Array,Date

二、包裝對象:基本類型都有本身對應的包裝對象:String,Number,Boolean

  var str='hello';//基本類型:字符串類型

  str.charAt(0);//基本類型會找到對應的包裝對象類型,而後包裝對象把全部的屬性和方法給了基本類型,而後包裝對象消失。

  str.number=10;//在包裝對象下創一個對象,將屬性建立在對象下面,而後包裝對象就消失了,

  alert(str.number);//會彈出undefined;緣由:會在包裝對象下從新建立一個對象

 


 

3、原型鏈

  原型鏈:實例對象與原型之間的鏈接,叫作原型鏈  

  _proto_(隱式鏈接)

   Object對象類型是原型鏈的最外層

  

  實例對象->先查找本身自己下面的屬性和方法->自身沒找到會沿着原型鏈找到該對象的原型,再查看原型上是否有要查找的屬性或方法->依次繼續查找若是找到的話則返回,不然找到最頂層Object上尚未就真沒有了

 


 

4、面向對象中的屬性和方法 

 一、hasOwnProperty():看是否爲對象自身下面的屬性和方法

  只有對象本身定義的屬性和方法則返回true,若是在prototype下定義發屬性和方法爲公用的,因此返回爲false;

二、constructor:查看對象的構造函數

  (能夠用來檢測函數類型例如檢測是不是數組)

  每一個原型函數都會自動添加constructor屬性(只會生成這一個屬性)

  for in的時候有些屬性是找不到的(系統自帶的屬性是for in找不到的,本身定義的能夠找到)

  避免修改constructor屬性

function Aaa(){}
//Aaa.prototype.name='小米';
//Aaa.prototype.age=6;
//alert(a1.constructor);//Aaa 緣由:只是給原型添加了屬性,並非從新賦值了,自動添加的constructor屬性還在。
Aaa.prototype={
//  constructor:'Aaa',//須要手動修正指向問題
  name:'小米',
  age:6
}
var a1=new Aaa();
alert(a1.constructor);//Object 緣由:將原型的prototype從新賦值了,但裏面沒有constructor

 注意:以這種方式重設constructor屬性會使它的[Enumerable]特性被設置爲true,默認狀況下,原生的constructor屬性是不可枚舉的。能夠經過Object.defineProperty()來修改。

三、instanceof:運算符

  對象與構造函數在原型鏈上是否有關係,也能夠用做類型判斷但不是最好的方案,最好的方案是用toString 方法來判斷。

四、toString():object上的方法,把對象轉化爲字符串

var arr=[];
alert(arr.toString==Object.prototype.toString);//false
//緣由:系統對象下面都是自帶的(例如數組的toString在Array.prototype下),本身寫的對象都是經過原型鏈找到object下面的toString
function Aaa(){}
var a1=new Aaa();
alert(a1.toString==Object.prototype.toString);//true

1>利用toString 進制轉化

 Number.toString(進制);

var num=255;
alert(num.toString(16));//ff---轉化爲16進制,默認不寫轉化爲十進制

2>利用toString作類型判斷:

  //跨頁面的狀況下上面兩種狀況會失效

 var oF=document.createElement('iframe');

  document.body.appendChild('oF');

  var ifArray=windows.frames[0].Array;//iframe下的Array數組

  var arr=new ifArray();

  alert(arr.constructor==Array);//false

  alert(arr instanceof Array);//false

  alert(Object.prototype.toString.call(arr)=='[object Array]');//true

 

var arr=[];
alert(Object.prototype.toString.call(arr));//[Object Array] 
var arr={};
alert(Object.prototype.toString.call(arr));//[Object Object] 
var arr=new Date;
alert(Object.prototype.toString.call(arr));//[Object Date] 
var arr=new RegExp;
alert(Object.prototype.toString.call(arr));//[Object RegExp]  
var arr=null;
alert(Object.prototype.toString.call(arr));//[Object Null] 

 


 

 

五 、繼承

一、繼承方式:

  一、拷貝繼承:通用型  有new無new均可以用

  二、類式繼承:new構造函數---利用構造函數(類)繼承的方式

  三、原型繼承:無new的對象---藉助原型來實現對象繼承對象

  屬性繼承:調用父類的構造函數call

  方法繼承:用for in的形式 拷貝繼承(jq也用拷貝繼承)

        var a = {
            name: '小米'
        };
        //拷貝繼承
        function extend(obj1, obj2) {
            for (var attr in obj2) {
                obj1[attr] = obj2[attr];
            }
        }
        //原型繼承
            var b=cloneObj(a);
            b.name='小喬';
            alert(a.name);
            alert(b.name);
            function cloneObj(obj) {
                var F=function () {};
                F.prototype=obj;
                return new F();
            }
        //類式繼承
        function A() {//父類
            this.name='小米';
        }
        A.prototype.showName=function () {
            alert(this.name);
        }
        function B() {//子類
            A.call(this);//屬性和方法分開繼承
        }    //B.prototype=new A();//一句話實現繼承,但會有不少問題,好比指向問題,屬性會互相影響    //類式繼承改進:至少由如下四句實現方法的繼承,屬性須要分開繼承
        var F=function () {};
        F.prototype=A.prototype;
        B.prototype=new F();
        B.prototype.constructor=A;//修正指向問題
        var b1=new B();
        b1.name='笑笑';
        b1.showName();
相關文章
相關標籤/搜索