【Javascript】new一個函數和直接調用函數的區別以及new一個對象的過程


一、new一個函數和直接調用函數的區別

不使用new,也就是普通的函數調用而已,所以若是函數本身沒有返回值,普通的函數調用沒有什么意義
如:
var person=new Person();//person是一個對象

var person = Person();//這只是一次普通的函數調用並賦值而已。

function Person(name,age){  
  
this.name=name;  
this.age=age;  
this.sayName=function(){  
alert(this.name);  
      };  
}  
  
//var person=new Person("張三",20); //此處為 構造對象,構造對象的話,返回的新對象是由解析器自己生成的。  
var person=Person("張三",20); //假設我在Person函數里面加了return "你好"; 這時的person就不會報undefined,而是一個字符串你好  
person.sayName();//報錯 person undefined 此處為普通函數調用,又沒有給定返回值,出錯。  
  
//因為此時this指向window對象,  
window.sayName();//此時不會報錯  
  
//接下來就問,為什么我賦值給person,可以用window來引用呢?  
//因為如果不用new就相當於普通函數調用,而 Person()根本沒有返回值,  
//所以Person根本就沒賦值給person,此時的person只是一個undefined,  
//但是Person卻執行了一次,成為了window的對象,this指向了window,所以window可以直接使用Person的方法, 

如果構造函數返回值為常規意義上的數值類型(Number、String、Boolean)時,new函數將會返回一個該函數的實例對象,

而如果構造函數返回一個引用類型(Object、Array、Function)時,則new函數與直接調用函數產生的結果相同,都返回這個引用。

  • 函數返回值為常規意義上的數值類型(Number、String、Boolean)
function Test()  
  {  
      this.name = "test";  
      return "test";  
  }  
  var test1 = new Test();   //Object 對象,它有一個name 屬性,並且返回一個字符串test  
  var test2 = Test();    // 函數Test()屬於Function對象   這個test2,它單純是一個字符串

  • 函數返回一個引用類型(Object、Array、Function)(工廠模式):
function Person(name,age) 
    { 
        var o = new Object(); 
        o.name = name; 
        o.age = age; 
        o.getName = function() 
        { 
            alert(this.name); 
        } 
        return o; 
    } 
    var obj1 = new Person("liwen",25); 
    var obj2 = Person("liwen1",25); 
    obj1.getName();  //liwen       new一個函數的實例對象  
    obj2.getName();  //liwen1      直接調用  

二、new一個對象的過程

首先我們看下new Person輸出什么?

var Person = function(name, age) {
        this.name = name;
        this.age = age;
    };
    Person.prototype.show = function() {
        console.log(this.name, this.age);
    };
    var p = new Person("bella", 10);
    console.log(p);

對象p里有屬性name, age 和 __proto__;

__proto__里面有原型方法show,constructor, __proto__;

然后我們再輸出構造器Person.prototype:

對比一下,發現p的__proto__的值就是構造函數Person的prototype的屬性值。

因此new操作符創建對象可以分為以下四個步驟:

    • 創建一個空對象
    • 將所創建對象的__proto__屬性值設為構造函數的prototype的屬性值
    • 執行構造函數中的代碼,構造函數中的this指向該對象
    • 返回對象

因此上面的過程就可以等同於下面的過程:

var newMethod2 = function(Class,...rest){
    var p = {};
    p.__proto__ = Class.prototype;
    var result = Class.apply(p, rest);
    return typeof result==='object'?result:p;

}

 


免責聲明!

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



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