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


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

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

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

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

三:實例

js兩種定義函數的方式:

<!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函數體內(執行作用域)聲明的變量,無論在函數體何處聲明,它將都會被提升到函數的頂部,我們稱這種現象為變量提升。 
函數呢,它也有這種特性,即無論在函數體何處聲明另一個函數,它將都會被提升到函數的頂部。
只是采用函數表達式和函數聲明所體現的函數提升的內容是有差別的:函數表達式和變量提升類似,只會提升函數的變量,不提升函數的定義;
而函數聲明提升時,不僅僅會提升函數的聲明,函數的定義也會被提升

對象冒充:臨時屬性

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():

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

原型鏈繼承:無new

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方式定義的變量和方法,如以下代碼將會出錯:

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()沒有參數。

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(); 

結論:

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

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();


免責聲明!

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



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