1. 程式人生 > >JS中的建構函式與與原型物件的理解

JS中的建構函式與與原型物件的理解

一:JS中的建構函式

在這裡可以這樣理解建構函式 ,即構造一個物件的函式就叫做建構函式;

1:那麼我們使用建構函式的目的是構造一個物件 ,如何構造一個物件就是我下面要說的:

在JavaScript中,任何合法的函式都可以作為物件的建構函式,這包括系統內建的函式,

也包括自己定義的函式。

注意:(一旦函式被作為建構函式執行,他內部的this屬性將引用函式本身;)

在我們一般的學習中,一般建構函式都沒有返回值,因為建構函式的內部就是一些屬性和方法的定義,

還有這些屬性的初始化(或者說這些屬性和方法只是初始化有this指標傳遞進來的物件),因此我們通常不需要返回值,

總的來說從形式上來看,一個函式被作為建構函式還是普通函式執行的唯一區別就是是否使用 new運算子;;4

下面舉個小李子你就會很容易理解,就不做太多解釋啦!

function Student(name,age,gender) {
    this.name=name;
    this.age=age;
    this.gender=gender;
    this.sayHello=function(){
        console.log('你好:'+this.name);
    };
    //console.log(this);
}

//如果這兩行程式碼執行的話會出現  ”Cannot read property 'sayHello' of undefined“的錯誤;
//因為此時的this指向是window,而window物件中並沒有定義過sayHello這個方法;
//var stu1=Student('wang','20','man');
//stu1.sayHello();

//會正常執行,打印出:”你好:wang“;
//此時當前stu2物件內的this指標指向的是當前物件,因此可以訪問到我們再呼叫建構函式傳入的引數值
var stu2=new Student('wang','20','man');
stu2.sayHello();

console.log('程式結束!');

那麼下面我們討論一下返回值的情況分為函式的返回值是引用型別和值型別的兩種情況:

(1);返回值為引用型別的函式

如果一個函式的返回值是引用型別(例如是:陣列,物件,函式)的資料,那麼這個函式被作為

建構函式用new運算子執行時,運算的結果將被他的返回值取代,這時,建構函式體內的this

即指向原建構函式構造出來的物件指標丟失了,此時返回的是被return 的物件;

function test() {
    this.a=10;
    return function(){
        return 1;
    };
}

var m =new test();

var n = test();

console.log(m());//打印出1;
console.log(n());//打印出1;

可以看到執行結果 m和n的值是一樣的,都是test函式的閉包,而this引用的物件和this.a=10的賦值結果都 被丟棄;

(2)返回值為值為值型別的函式

如果一個函式的返回值是一個值型別,那麼這個函式作為建構函式用new 運算子執行構造時,他的返回值將會被丟棄;

new 表示式的結果仍然是this所引用的物件;

function test() {
    this.a=10;
    return 1;
}

var m=new test();

//不使用new時,就是呼叫返回值為1 的test函式,this指標指向window,
//this.a相當於給window物件添加了一個a屬性,且屬性值為10;
var n =test();

console.log(m);//打印出:test { a: 10 }
console.log(n);//打印出:1

二:JS中的原型物件的理解

在JS中當我們建立一個新的函式時 ,同時也會自動為該函式建立一個prototype的屬性,

這個屬性指向函式的原型物件;

注意:在預設的情況下,所有的原型物件均會有一個constructor屬性,這個屬性也是一個指標 ,

指向建構函式;

所以可以這樣看,建構函式的prototype屬性指向原型物件,原型物件中的constructor屬性指向建構函式;

下面來看這個例子:

//建立一個Person建構函式,(其實建構函式就是一個構造物件的函式,也就是一個不需要返回值的函式)
function Person() {}

//在建構函式的原型上面新增屬性和方法
Person.prototype.name='wang';
Person.prototype.age=20;
Person.prototype.gender='man';
Person.prototype.SayHello=function(){
    return '你好:'+this.name;
}

//例項化兩個物件 
var person1=new Person();
var person2=new Person();

console.log(person1.SayHello());//打印出:你好:wang

可以看到上面的第一行程式碼中,在Person建構函式中,其中除了預設的一個 prototype屬性,並沒有任何的屬性和方法,

而且我們構造出來的person1例項上除了內部屬性 [[prototype]],也是什麼都沒有,但是當我們

訪問person1.sayHello的時候會有返回值呢?

以下是對這個問題的解釋:

(1)當我們訪問一個物件時,

如果該物件存在這個屬性,則返回這個屬性;

注意:(如果當前屬性和原型上的屬性相同時,則不會去訪問原型物件上的屬性 ,

如果想要去訪問原型上的這個相同的屬性,可以刪除當前物件上的這個屬性即可)

{

          如果該物件不存在這個屬性,則取這個物件上的原型上面去尋找,

                         {

                              如果原型上面存在這個屬性,則返回這個屬性的屬性值;

                              如果原型上面不存在這個屬性,則返回一個undefined;

                         }

}

(2)當我們為一個物件新增屬性時,他首先會檢查當前物件上是否存在這個屬性 ;

如果沒有,則新增這個屬性並且進行賦值;(注意其不會去原型上去尋找zhe'ge')

如果有,則修改成你賦予的值;