題目:
小賢是一條可愛的小狗(Dog),它的叫聲很好聽(wow),每次看到主人的時候就會乖乖叫一聲(yelp)。從這段描述可以得到以下對象:
function Dog() {
this.wow = function() {
alert(’Wow’);
}
this.yelp = function() {
this.wow();
}
}
小芒和小賢一樣,原來也是一條可愛的小狗,可是突然有一天瘋了(MadDog),一看到人就會每隔半秒叫一聲(wow)地不停叫喚(yelp)。請根據描述,按示例的形式用代碼來實現(提示關鍵字: 繼承,原型,setInterval)。
知識點:
(1)原型鏈:ECMAScript中描述了原型鏈的概念,並將原型鏈作為實現繼承的主要方法。其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。
簡單回顧一下構造函數、原型和實例之間的關系:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的
內部指針。那么,假如我們讓原型對象等於另一個類型的實例,顯然,此時的原型對象將包含一個指向另一個原型的指針,相應地,另一個原型中也包含着一個指
向另一個構造函數的指針。
(2)組合繼承:也叫做偽經典繼承,指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮二者之長的一種繼承模式。其背后的思路是使用原型鏈實現對原型
屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣,既通過在原型上定義方法實現了函數復用,又能夠保證每個實例都有它自己的屬性。
function SuperType(name){
this.name = name;
this.colors = [“red”, “blue”, “green”];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
//inherit properties
SuperType.call(this, name);
this.age = age;
}
//inherit methods
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType(“Nicholas”, 29);
instance1.colors.push(“black”);
alert(instance1.colors); //”red,blue,green,black”
instance1.sayName(); //”Nicholas”;
instance1.sayAge(); //29
var instance2 = new SubType(“Greg”, 27);
alert(instance2.colors); //”red,blue,green”
instance2.sayName(); //”Greg”;
instance2.sayAge(); //27
(3)setTimeout函數:Executes a code snippet or a function after specified delay.
var timeoutID = window.setTimeout(code, delay);
timeoutID
is the numerical ID of the timeout, which can be used later with window.clearTimeout.
(4)setInterval函數:Calls a function repeatedly, with a fixed time delay between each call to that function.
var intervalID = window.setInterval(code, delay);
intervalID
is a unique interval ID you can pass to clearInterval()
.
(5)setTimeout和setInterval的區別:The setInterval function also delays for a specified time before triggering the execution of a specific function. Where it differs is that after triggering that function the command doesn't complete. Instead it waits for the specified time again and then triggers the function again and continues to repeat this process of triggering the function at the specified intervals until either the web page is unloaded or the clearInterval function is called.
(6)閉包中的this對象:在閉包中使用this對象也可能會導致一些問題。我們知道,this對象是在運行時基於函數的執行環境綁定的:在全局函數中,this等於window,
而當函數被作為某個對象的方法調用時,this等於那個對象。不過,匿名函數的執行環境具有全局性,因此其this對象通常指向window。但有時候由於編寫閉包的方式 不同,這一點可能不會那么明顯。例如:
var name = “The Window”;
var object = {
name : “My Object”,
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //”The Window”
以上代碼先創建了一個全局變量name,又創建了一個包含name屬性的對象。這個對象還包含一個方法——getNameFunc(),它返回一個匿名函數,而匿名函數又返回
this.name.由於getNameFunc()返回一個函數,因此調用object.getNameFunc()()就會立即調用它返回的函數,結果就是返回一個字符串。然而,這個例子返回的字符
串是“The Window”,即全局name變量的值。它的原因在於,每個函數在調用時,其活動對象都會自動取得兩個特殊變量:this和arguments。內部函數在搜索這兩個 變量時,只會搜索到其活動對象為止,因此永遠不可能直接訪問外部函數中的這兩個變量。不過,把外部作用域中的this對象保存在一個閉包能夠訪問到的變量里,就可 以讓閉包訪問該對象了,如下所示:
var name = “The Window”;
var object = {
name : “My Object”,
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //”My Object”
答案:
<!DOCTYPE html>
<html>
<head>
<style type="text/css" rel="stylesheet">
</style>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
window.onload=function()
{
function Dog(name){
this.name=name;
}
Dog.prototype={
constructor:Dog,
Wow:function(){
console.group();
console.info("I am: "+this.name);
console.info("WangWang....");
console.groupEnd();
},
yelp:function(){
this.Wow();
}
};
function MadDog(name){
Dog.call(this,name);
}
MadDog.prototype=new Dog();
MadDog.prototype.constructor=MadDog;
MadDog.prototype.yelp=function()
{
self=this;
setInterval(function(){self.Wow();console.log(this);console.log(self);},500);
}
var xiaoXian=new Dog("xiaoXian");
xiaoXian.yelp();
var xiaoMang=new MadDog("xiaoMang");
xiaoMang.yelp();
}
</script>
</html>