1、 OOP 指什么?有哪些特性
OOP是Object-oriented programming的縮寫,指面向對象程序設計。
在面向對象程序設計中有兩個重要概念
類:
類是對現實生活中一類具有共同特征的事物的抽象。對象:
對象是類的實例,對象包含屬性和方法,屬性是需要記憶的信息,方法是對象能夠提供的服務。
特性
繼承
子類能繼承父類的屬性和方法
子類能添加新的屬性和方法,還能重寫父類的屬性和方法封裝
隱藏對象的屬性和實現細節,僅對外公開接口多態
指同一個實體同時具有多種形式,同一操作作用于不同對象,可以有不同的解釋,產生不同的執行結果。
2: 如何通過構造函數的方式創建一個擁有屬性和方法的對象?
2.1 構造函數
面向對象編程的第一步,就是要生成對象。
對象是單個實物的抽象。通常需要一個模板,表示某一類實物的共同特征,然后對象根據這個模板生成。
典型的面向對象編程語言(比如 C++ 和 Java),存在“類”(class)這個概念。所謂“類”就是對象的模板,對象就是“類”的實例。但是,JavaScript 語言的對象體系,不是基于“類”的,而是基于構造函數(constructor)和原型鏈(prototype)。
JavaScript 語言使用構造函數(constructor)作為對象的模板。所謂”構造函數”,就是專門用來生成對象的函數。它提供模板,描述對象的基本結構。一個構造函數,可以生成多個對象,這些對象都有相同的結構。
構造函數的寫法就是一個普通的函數,但是有自己的特征和用法。
var Vehicle = function () {
this.price = 1000;
};
上面代碼中,Vehicle就是構造函數,它提供模板,用來生成實例對象。為了與普通函數區別,構造函數名字的第一個字母通常大寫。
構造函數的特點有兩個。
函數體內部使用了this關鍵字,代表了所要生成的對象實例。
生成對象的時候,必需用new命令,調用Vehicle函數。
2.2 new 命令的原理
new命令的作用,就是執行構造函數,返回一個實例對象。
new運算符創建對象實例:new后面跟一個函數 F ,根據需要函數可以傳入參數,new F(arguments...)
。
使用new運算符創建對象實例這一過程分為四步:
創建一個空對象,作為將要返回的對象實例
將這個空對象的原型,指向構造函數的prototype屬性
將這個空對象賦值給函數內部的this關鍵字
開始執行構造函數內部的代碼(為實例對象添加屬性和方法)
也就是說,構造函數內部,this指的是一個新生成的空對象,所有針對this的操作,都會發生在這個空對象上。構造函數之所以叫“構造函數”,就是說這個函數的目的,就是操作一個空對象(即this對象),將其“構造”為需要的樣子。
如果構造函數內部有return語句,而且return后面跟著一個對象,new命令會返回return語句指定的對象;否則,就會不管return語句,返回this對象。
var Vehicle = function () {
this.price = 1000;
return 1000;
};
(new Vehicle()) === 1000
// false
上面代碼中,構造函數Vehicle的return語句返回一個數值。這時,new命令就會忽略這個return語句,返回“構造”后的this對象。
但是,如果return語句返回的是一個跟this無關的新對象,new命令會返回這個新對象,而不是this對象。這一點需要特別引起注意。
var Vehicle = function (){
this.price = 1000;
return { price: 2000 };
};
(new Vehicle()).price
// 2000
上面代碼中,構造函數Vehicle的return語句,返回的是一個新對象。new命令會返回這個對象,而不是this對象。
另一方面,如果對普通函數(內部沒有this關鍵字的函數)使用new命令,則會返回一個空對象。
function getMessage() {
return 'this is a message';
}
var msg = new getMessage();
msg // {}
typeof msg // "object"
上面代碼中,getMessage是一個普通函數,返回一個字符串。對它使用new命令,會得到一個空對象。這是因為new命令總是返回一個對象,要么是實例對象,要么是return語句指定的對象。本例中,return語句返回的是字符串,所以new命令就忽略了該語句。
如果忘了使用new命令,直接調用構造函數會發生什么事?
這種情況下,構造函數就變成了普通函數,并不會生成實例對象this這時代表全局對象,將造成一些意想不到的結果。
var Vehicle = function (){
this.price = 1000;
};
var v = Vehicle();
v.price
// Uncaught TypeError: Cannot read property 'price' of undefined
price
// 1000
上面代碼中,調用Vehicle構造函數時,忘了加上new命令。結果,price屬性變成了全局變量,而變量v變成了undefined。
通過構造函數的方式創建一個擁有屬性和方法的對象:
function People(name,color){
this.name=name;
this.color=color;
this.sayname=function(){
console.log(this.name);
}
}
var person1=new People('xuguojun','red')
3: prototype 是什么?有什么特性
我們創建的每個函數都有一個 prototype(原型)屬性。使用原型的好處是可以讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構造函數中定義對象實例的信息,而是可以將這些信息直接添加到原型中,如下面的例子所示。
function Person(){}
Person.prototype.name = "Stone";
Person.prototype.age = 28;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
console.log(this.name);
};
var person1 = new Person();
person1.sayName(); // "Stone"
var person2 = new Person();
person2.sayName(); // "Stone"
console.log(person1.sayName == person2.sayName); // true
再來看一幅圖:
通過圖示我們可以看出一些端倪,實例可以通過prop訪問到其類型的prototype屬性,這就意味著類的prototype對象可以作為一個公共容器,供所有實例訪問。
4:畫出如下代碼的原型圖
function People (name){
this.name = name;
this.sayName = function(){
console.log('my name is:' + this.name);
}
}
People.prototype.walk = function(){
console.log(this.name + ' is walking');
}
var p1 = new People('徐國軍');
var p2 = new People('前端');
5. 創建一個 Car 對象,擁有屬性name、color、status;擁有方法run,stop,getStatus
function Car(name,color,status){
this.name = name;
this.color = color;
this.status = status;
}
Car.prototype.run = function(){
console.log('running');
};
Car.prototype.stop = function(){
console.log('stop');
};
Car.prototype.getStatus = function(){
console.log(this.status);
};
var newCar = new Car('蘭博基尼','black',0);
newCar.run();
newCar.stop();
newCar.getStatus();
6: 創建一個 GoTop 對象,當 new 一個 GotTop 對象則會在頁面上創建一個回到頂部的元素,點擊頁面滾動到頂部。擁有以下屬性和方法
-
ct
屬性,GoTop 對應的 DOM 元素的容器
-
-
target
屬性, GoTop 對應的 DOM 元素
-
-
bindEvent
方法, 用于綁定事件
-
- 4
createNode
方法, 用于在容器內創建節點
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
<style id="jsbin-css">
.goTop{
border: 1px solid yellow;
width: 110px;
height: 40px;
line-height: 40px;
text-align: center;
background: yellow;
cursor: pointer;
position: fixed;
bottom: 20px;
right: 20px;
}
</style>
</head>
<body>
<div class="ct">
<p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容1</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容2</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p><p>內容3</p>
</div>
<script>
function GoTop($ele){
this.ct=$ele;
this.target=$('<div class="goTop">回到頂部</div>');
this.init();
};
GoTop.prototype={
init:function(){
this.createNode();
this.bindEvent();
},
createNode:function(){
var me=this;
me.target.hide();
$('body').append(me.target);
$(window).on('scroll',function(){
if($(window).scrollTop()>300){
me.target.show();
}else{
me.target.hide();
}
});
},
bindEvent:function(){
var me=this;
me.target.on('click',function(){
$(window).scrollTop(0);
})
}
}
var go=new GoTop( $('body') );
</script>
</body>
</html>