構造函數的基本特性與優缺點


構造函數:如用函數用來初始化(使用new運算符)一個新建的對象,我們稱之為構造函數(constructor)
function Person(){
    this.name = "zqq";
    this.age = 28;
}
var p = new Person();

當以new調用構造函數(執行var p = new Person())時,函數內部會發生以下情況:

1.創建一個空對象

var p = {};

2.this變量指向對象p

Person.call(p)

3.p繼承了構造函數Person()的原型

p.__proto__ = Person.prototype

4.執行構造函數Person()內的代碼

構造函數和普通函數的區別:

1.構造函數使用new關鍵字調用;普通函數不用new關鍵字調用;

var p = new Person();
var p = Person();

2.構造函數內部可以使用this關鍵字;普通函數內部不建議使用this,因為這時候this指向的是window全局對象,這樣無意間就會為window添加了一些全局變量或函數

在構造函數內部,this指向的是構造出來的新對象

在普通函數內部,this指向的是window全局對象

3.構造函數默認不用return返回值;普通函數一般都有return返回值

構造函數會默認返回this,也就是新的實例對象

普通函數如果沒有return值的話,返回undefined

如果使用了return,那返回值會根據return值的類型而有所不同
return的是五種簡單數據類型:String,Number,Boolean,Null,Undefined的話,構造函數會忽略return的值,依然返回this對象;而普通函數會返回return后面的值

function Person(){
    var a;
    this.name = "zqq";
    this.age = 28;
    return a;
}
var p = new Person();//返回this對象
var p = Person();//因為a沒初始化,所以a是undefined,而undefined屬於簡單數據類型,所以返回undefined,String,Number,Boolean,Null同理


如果return的是引用類型:Array,Date,Object,Function,RegExp,Error的話,構造函數和普通函數都會返回return后面的值

function Person(){
    var arr = [];
    this.name = "zqq";
    this.age = 28;
    return arr;
}
var p = new Person();//返回arr空數組,Date,Object,Function,RegExp,Error同理
var p1 = new Person();//返回arr空數組,Date,Object,Function,RegExp,Error同理  

4.構造函數首字母建議大寫;普通函數首字母建議小寫

構造函數的優點與缺點

優點就是能夠通過instanceof識別對象,缺點是每次實例化一個對象,都會把屬性和方法復制一遍

function CreateObj(uName) {
              this.userName = uName;
              this.showUserName = function () {
              return this.userName;
            }
        }

var obj1 = new CreateObj('ghostwu');
var obj2 = new CreateObj('衛庄');

console.log( obj1.showUserName === obj2.showUserName ); //false

從以上執行結果,可以看出obj1.showUserName和obj.showUserName不是同一個【在js中,引用類型比較的是地址, 函數是一種引用類型】,而是存在兩個不同
的內存地址,因為每個對象的屬性是不一樣的,這個沒有什么問題,但是方法執行的都是一樣的代碼,所以沒有必要復制,存在多份,浪費內存.這就是缺點

怎么解決構造函數的方法復制多次的問題?

function CreateObj(uName) {
  this.userName = uName;
  this.showUserName = showUserName;
}
function showUserName() {
  return this.userName;
}
var obj1 = new CreateObj('ghostwu');
var obj2 = new CreateObj('衛庄');
console.log(obj1.showUserName === obj2.showUserName); //true

把對象的方法指向同一個全局函數showUserName, 雖然解決了多次復制問題,但是全局函數非常容易被覆蓋,也就是大家經常說的污染全局變量.

比較好的解決方案?

通過原型(prototype)對象,把方法寫在構造函數的原型對象上

function CreateObj(uName) {
  this.userName = uName;
}
CreateObj.prototype.showUserName = function () {
  return this.userName;
}
var obj1 = new CreateObj('ghostwu');
var obj2 = new CreateObj('衛庄');
console.log(obj1.showUserName === obj2.showUserName); //true

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM