js兩種定義函數、繼承方式及區別

一:js兩種定義函數的方式及區別

  • 1:函數聲明:
function  sayA() {   alert("i am A");  }
  • 2:函數表達式:
var sayB = function() {   alert("i am B");  }
前者會在代碼執行以前提早加載到做用域中,後者則是在代碼執行到那一行的時候纔會有定義

二:js兩種繼承方式及區別

  • 對象冒充
    • 臨時屬性
    • call()
    • apply()
  • 原型鏈 code
  • 繼承應選哪一種 code

三:實例

js兩種定義函數的方式:javascript

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>js兩種定義函數的方式</title>
<script language="javascript">
    say(); 
    var say =function(){
        alert("567");
    }
    function say(){
        alert("123");
    }  
</script>
</head>
<body>
</body>
</html>
//在javascript函數體內(執行做用域)聲明的變量,不管在函數體何處聲明,它將都會被提高到函數的頂部,咱們稱這種現象爲變量提高。 
函數呢,它也有這種特性,即不管在函數體何處聲明另外一個函數,它將都會被提高到函數的頂部。
只是採用函數表達式和函數聲明所體現的函數提高的內容是有差異的:函數表達式和變量提高相似,只會提高函數的變量,不提高函數的定義;
而函數聲明提高時,不單單會提高函數的聲明,函數的定義也會被提高

對象冒充:臨時屬性html

function Person(name){
     this.name = name;
     this.say = function(){
        alert('My name is '+this.name);
     }
}
function Student(name,id){
    this.temp = Person;
    this.temp(name); 
    delete this.temp;
    this.id = id; 
    this.showId = function(){
       alert('Good morning,Sir,My student number is '+this.id);
    }
}
var simon = new Student('Simon',9527);
simon.say(); //my name id simon
simon.showId(); //Good morning,Sir,My work number is 9527

對象冒充:apply()/call():java

function Person(name){
    this.name = name;
    this.say = function(){
      alert('My name is '+this.name);
    }
}
function Student(name,id){
     Person.call(this,name); //apply():Person.apply(this,new Array(name));
     this.id = id;
     this.showId = function(){
        alert('Good morning,Sir,My student number is '+this.id);
     }
}
var simon = new Student('Simon',9527);
simon.say();
simon.showId();
//apply(this,arguments):方法能劫持另一個對象的方法,繼承另一個對象的屬性. 
                        arguments:是一個數組,new Array(name,age)等
//call(id,name,age)
//什麼狀況下用apply,什麼狀況下用call  
在給對象參數的狀況下,若是參數的形式是數組的時候,
好比apply示例裏面傳遞了參數arguments,這個參數是數組類型,
而且在調用Person的時候參數的列表是對應一致的(也就是Person
和Student的參數列表前兩位是一致的) 就能夠採用 apply , 
若是個人Person的參數列表是這樣的(age,name),而Student
的參數列表是(name,age,grade),這樣就能夠用call來實現了,
也就是直接指定參數列表對應值的位置(Person.call(this,age,name,grade));  
//apply和call中的參數順序以父類爲準。

原型鏈繼承:new數組

var Shape = function(width, height) {
    this.width = width;
    this.height = height;
};
Shape.prototype.area = function() {
    return this.width * this.height
};
var shape = new Shape(20, 30);
shape.area();
> 600

原型鏈繼承:無newapp

function Shape(width, height) {
    if (!(this instanceof Shape)) {
        return new Shape(width, height);
    }
    this.width = width;
    this.height = height;
    return this;
}   
Shape.prototype.area = function() {
    return this.width * this.height
};
var shape = Shape(20, 30);
console.log(shape.area());

 

選擇最優繼承方式:函數

1:在OO概念中,new實例化後,對象就在堆內存中造成了本身的空間, 值得注意的是,這個代碼段。而成員方法就是存在這個代碼段的, 而且方法是共用的。問題就在這裏,經過對象冒充方式繼承時, 全部的成員方法都是指向this的,也就是說new以後,每一個實例將 都會擁有這個成員方法,並非共用的,這就形成了大量的內存浪費。 而且經過對象冒充的方式,沒法繼承經過prototype方式定義的變量和方法,如如下代碼將會出錯:ui

function Person(name){
    this.name = name;
    this.say = function(){
       alert('My name is '+this.name);
    }
}
Person.prototype.age = 20;
Person.prototype.sayAge = function(){alert('My age is '+this.age)};
function Student(name,id){
     Person.apply(this,new Array(name));
         this.id = id;
         this.showId = function(){
         alert('Good morning,Sir,My student number is '+this.id);
     }
}

var simon = new Student('Simon',9527);
simon.sayAge(); //提示TypeError: simon.sayAge is not a function

2:原型鏈方式繼承,就是實例化子類時不能將參數傳給父類,這個例子中function Person()沒有參數。this

function Person(name){
    this.name = name;
}
Person.prototype.say = function(){
    alert('My name is '+this.name);
}
function Student(name,id){
    this.id = id;
    this.showId = function(){
       alert('Good morning,Sir,My student number is '+this.id);
 }
}
Student.prototype = new Person();
//此處沒法進行傳值,this.name或者name都不行,
//直接寫Student.prototype = new Person('wood')是能夠的,
//可是這樣的話simon.say()就變成了My name is wood
var simon = new Student("Simon",9527);
simon.say();  //彈出 My name is undefined
simon.showId();

結論:spa

成員變量採用對象冒充方式,成員方法採用原型鏈方式

function Person(name){
    this.name = name;
}
Person.prototype.say = function(){
    alert('My name is '+this.name);
}
function Student(name,id){
    Person.call(this,name);
    this.id = id;
}
Student.prototype = new Person(); 
//此處注意一個細節,showId不能寫在Student.prototype = new Person();前面
Student.prototype.showId = function(){
    alert('Good morning,Sir,My student number is '+this.id);
}
var simon = new Student("Simon",9527);
simon.say();
simon.showId();
相關文章
相關標籤/搜索