權威指南學習心得-類

構造函甚至沒必要返回這個新建立的對象,構造函數會自動建立對象,而後將構造函數看成爲這個對象的方法來調用一次,最後返回這個新對象。javascript

當使用instanceof運算符來檢測對象是否屬於某個類時會用到構造函數java

r instanceof Range//若是r繼承自range.prototype,則返回trueecmascript

實際上instranceof運算符並不檢查r是否由range構造函數初始化而來,而是檢查r是否繼承自range.prototype.函數

若是o繼承自c.prototype,則表達式o instanceof c值爲true,這裏的繼承能夠不是直接繼承,若是o所繼承的對象繼承自另外一對象,後一個對象繼承自c.prototype,這個表達式的運算結果也是true。this

若是你檢測對象的原型鏈上是否存在某個特定的原型對象,有沒有不使用構造函數做爲中介的方法麼?答案是確定的,能夠使用isPrototypeOf()方法。spa

constructor 另外一種識別對象是否屬於某個類的方法是constructor屬性。由於構造函數是類的公共標識符,因此最直接的方法就是使用constructor屬性。prototype

function typeAndValue(x){
  if(x==null)return "";
  switch(x.constructor){
    case Number:return "Nuber: "+x;
    case String: return "String:'"+x+"'";
    case Date: return "Date:"+x;
       case RegExp: return "RegExp"+x;
  }
}
console.log(typeAndValue(1));//Nuber: 1
console.log(typeAndValue("1"));//String:'1'
console.log(typeAndValue(new Date()));//Date:Tue Dec 22 2015 19:42:15 GMT+0800 (中國標準時間)

 

任何javascript函數均可以用做構造函數,而且調用構造函數是須要用到一個prototype屬性的。所以,每一個javascript函數(除了ecmascript 5中的Function.bind方法返回的函數以外)都自動擁有一個prototype屬性。這個屬性的值是一個對象。這個對象包含惟一一個不可枚舉屬性constructor。constructor屬性的值是一個函數對象。code

function f(){};
var p=f.prototype;
var c=p.constructor;
console.log(c);//function f(){}
console.log(p);//f {}
console.log(c===f);//true

對任意函數F.prototype.constructor==F;對象

能夠看到構造函數的原型中存在預先定義好的constructor屬性,這意味這對象一般繼承的constructor均指代它們的構造函數,因爲構造函數是類的公共標識,所以這個constructor屬性爲對象提供哦了類blog

var o=new F();

o.constructor===F;//true

range類使用它自身的一個新對象重寫了預約義的rang.prototype對象,這個新定義的原型對象不含有constructor屬性。所以range類的實例也不含有constructor屬性,咱們能夠經過補救來修正這個問題,顯示的給原型添加一個構造函數:

function Range(){
  this.x=1;
  this.y=2;
};
Range.prototype={
  constructor:Range
};


var p=new Range();

console.log(p.constructor);

另外一種常見的解決方法是使用預約義的原型對象,預約義的原型對象包含construtor屬性,而後依次給原型對象添加方法

類的擴充

String.prototype.trim=String.prototype.trim||function(){
  if(!this)return this;
  return this.replace(/^\s+|\s+$/g,"");
};

console.log("   sdf  ".trim());//sdf

Function.prototype.getName=function(){
  
  return this.Name|| this.toString().match(/function\s*([^()]*)\(/)[1];
  
};
function test(){
  
}
console.log(test.getName());//test

在javascipt中並不是全部的對象都包含constructor屬性。在每一個新建立的函數原型上默認會有constructor屬性,但咱們經常忽略原型上的constructor屬性。好比下面的實例就沒有constructor屬性

function F(){
  
}
F.prototype={};

var o=new F();

function inhernit(o){
  if(o==null) return null;
  function f(){};
  f.prototype=o;
  return new f();
  
}

var t=inhernit(o);

 

function type(o){
  var t,c, n;//type,class ,name
  //處理null值得特殊情形
  if(o===null) return "null";
  if(o!==o) return "nan";
  if((t=typeof o)!=="object"){
    return t;
  }
  
  if((c=classof(o))!=="Object"){
    return c;
  }
  if(o.constructor&&typeof o.constructor==="function"&&(n=o.constructor.getName())){
    return n;
  }
  
  return "Object";
}
function classof(o){
  return Object.prototype.toString.call(o).slice(8,-1);
}
Function.prototype.getName=function(){
  if("name" in this) return this.name;
  return  this.name=this.toString().math(/function\s*([^(]*)\(/)[1];
};
function test(){};
var p=new test();
console.log(type(p));

並非全部的對象都具備constructor屬性,此外,並非全部的函數都有名字,若是使用不帶名字的函數定義表達式定義一個構造函數,那麼getName方法則返回空字符串。

var complex=function(x,y){};//這個構造函數沒有名字

var range=function range(){};//這個構造函數有名字
相關文章
相關標籤/搜索