問(wèn)題1: OOP 指什么?有哪些特性
-
OOP:
“面向?qū)ο缶幊獭保∣bject Oriented Programming)是目前主流的編程范式。Java,JavaScript,C#,C+ +,Python,PHP,Ruby和Objective-C)都支持面向?qū)ο缶幊?。它的核心思想是將真?shí)世界中各種復(fù)雜的關(guān)系,抽象為一個(gè)個(gè)對(duì)象,然后由對(duì)象之間的分工與合作,完成對(duì)真實(shí)世界的模擬。每個(gè)對(duì)象都可以被看作是一個(gè)擁有清晰角色或責(zé)任的獨(dú)立小機(jī)器。
“傳統(tǒng)的過(guò)程式編程”(procedural programming)由一系列函數(shù)或一系列指令組成,而面向?qū)ο缶幊痰某绦蛴梢幌盗袑?duì)象組成。每一個(gè)對(duì)象都是功能中心,具有明確分工,可以完成接受信息、處理數(shù)據(jù)、發(fā)出信息等任務(wù)。因此,面向?qū)ο缶幊叹哂徐`活性、代碼的可重用性、模塊性等特點(diǎn),容易維護(hù)和開(kāi)發(fā),非常適合多人合作的大型軟件項(xiàng)目。 -
特性:
封裝性,繼承性,多態(tài)性
var Person = function (name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('hello');
}
var ethan = new Person('ethan');
ethan.sayHello();
var Man=function(){
this.sex="man";
}
Man.prototype.sayHello=function(){
console.log("hi");
}
var man1=new Man();
man1.sayHello();
//封裝性:把相對(duì)應(yīng)的變量和方法封裝到一起
//繼承性:ethan實(shí)例對(duì)象本身沒(méi)有定義sayHello,但是由于ethan是構(gòu)造函數(shù)Person的實(shí)例,繼承Person存放在prototype對(duì)象中的共有屬性和方法,所以可以調(diào)用sayHello。
//多態(tài)性:同一個(gè)方法可以有不同的表現(xiàn)。比如通過(guò)new兩個(gè)實(shí)例,可以分別對(duì)里面的方法函數(shù)擴(kuò)展,得到的結(jié)果不同,但是,這都屬于同一個(gè)方法。
問(wèn)題2: 如何通過(guò)構(gòu)造函數(shù)的方式創(chuàng)建一個(gè)擁有屬性和方法的對(duì)象?
function People(name,age){
this.name = name
this.age = age
this.sayName = function(){
console.log(this.name)
}
}
var p = new People('hunger','20')
p.sayName() //hunger
問(wèn)題3: prototype 是什么?有什么特性
JavaScript 的每個(gè)對(duì)象都繼承另一個(gè)對(duì)象,后者稱(chēng)為“原型”(prototype)對(duì)象。只有null除外,它沒(méi)有自己的原型對(duì)象。
原型對(duì)象上的所有屬性和方法,都能被派生對(duì)象共享。這就是 JavaScript 繼承機(jī)制的基本設(shè)計(jì)。
通過(guò)構(gòu)造函數(shù)生成實(shí)例對(duì)象時(shí),會(huì)自動(dòng)為實(shí)例對(duì)象分配原型對(duì)象。每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性就是實(shí)例對(duì)象的原型對(duì)象。
var Person = function (name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('hello');
}
var ethan = new Person('ethan');
ethan.sayHello();
//其中Person的prototype對(duì)象,就是ethan的原型對(duì)象。ethan.sayHello先在實(shí)例當(dāng)中找方法,若沒(méi)找到,就去prototype對(duì)象中找。
ethan.sayHello=function(){
console.log("hi");
}
ethan.sayHello();
//因?yàn)閑than實(shí)例當(dāng)中已經(jīng)有sayHello方法,所以不會(huì)再去原型上找方法
問(wèn)題4:畫(huà)出如下代碼的原型圖
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('前端');

問(wèn)題5: 創(chuàng)建一個(gè) Car 對(duì)象,擁有屬性name、color、status;擁有方法run,stop,getStatus
function Car(name,color,status){
this.init(name,color,status);
thsi.bind();
}
Car.prototype.init=function(name,color,status){
this.name=name;
this.color=color;
this.status=status;
}
Car.prototype.bind=function(){
this.run=function(){...};
this.stop=function(){...};
this.getStatus=function(){...};
}
問(wèn)題6: 創(chuàng)建一個(gè) GoTop 對(duì)象,當(dāng) new 一個(gè) GotTop 對(duì)象則會(huì)在頁(yè)面上創(chuàng)建一個(gè)回到頂部的元素,點(diǎn)擊頁(yè)面滾動(dòng)到頂部。擁有以下屬性和方法
1. `ct`屬性,GoTop 對(duì)應(yīng)的 DOM 元素的容器
2. `target`屬性, GoTop 對(duì)應(yīng)的 DOM 元素
3. `bindEvent` 方法, 用于綁定事件
4 `createNode` 方法, 用于在容器內(nèi)創(chuàng)建節(jié)點(diǎn)
問(wèn)題7: 使用木桶布局實(shí)現(xiàn)一個(gè)圖片墻
筆記:
1、 面向?qū)ο蟮某跣?/h6>
- 目的
1、改善可讀性
screenprint();
Screen.print();
2、提升重用性
1、改善可讀性
screenprint();
Screen.print();
2、提升重用性
2、原則:開(kāi)放封閉原則
1、對(duì)于擴(kuò)展是開(kāi)放的(open for extension)。當(dāng)應(yīng)用的需求改變時(shí),可以對(duì)模塊進(jìn)行擴(kuò)展,使其滿(mǎn)足改變的新行為。
2、 對(duì)于修改是關(guān)閉的(close for modification)。對(duì)模塊進(jìn)行擴(kuò)展時(shí),不必改變模塊的源代碼。
3、三要素:封裝,繼承,多態(tài)
1、封裝:把很多個(gè)屬性和方法封裝到一個(gè)對(duì)象當(dāng)中
2、繼承:繼承一個(gè)對(duì)象的所有的屬性和方法
3、多態(tài):不同的對(duì)象對(duì)同一個(gè)方法有不同的表現(xiàn)
4、實(shí)例化對(duì)象
var object=new Object();
2、 new操作
var object=new Object()時(shí),都發(fā)生了什么?
1、創(chuàng)建了一個(gè)空對(duì)象作為this
2、this.proto指向構(gòu)造函數(shù)的prototype
3、運(yùn)行構(gòu)造函數(shù)
4、返回this(如果構(gòu)造函數(shù)里沒(méi)有return,若存在return引用類(lèi)型,則返回return后的值)
var Foo=function(){
this.name="foo";
}
var foo=new Foo();
console.log(foo); //console.log(),console對(duì)象時(shí),先展示對(duì)象的構(gòu)造函數(shù)
//發(fā)生了什么?
1、創(chuàng)建了{(lán)},this指向{}
2、{}._proto_指向了Foo.prototype
3、執(zhí)行構(gòu)造函數(shù),{}.name="foo"
4、返回{}
var Foo=function(){
this.name="foo";
return {name:"foo1"};
}
var foo=new Foo();
console.log(foo); //console.log(),console對(duì)象時(shí),先展示對(duì)象的構(gòu)造函數(shù)
//發(fā)生了什么?
1、創(chuàng)建了{(lán)},this指向{}
2、{}._proto_指向了Foo.prototype
3、執(zhí)行構(gòu)造函數(shù),{}.name="foo"
4、返回{name:"foo1"}
3、如何手動(dòng)指定對(duì)象原型
//第一種:
var obj._proto_={...}; //ES6方法支持._proto_屬性,IE低版本不支持
//第二種:
var my={
name:"foo"
}
var obj={};
var Temp=functon(){};
Temp.prototype=my;
obj=new Temp(); //此時(shí)的constructor指向的是Temp
obj.constructor=my;
var Animal=function(){
this.種類(lèi)="動(dòng)物";
}
Animal.prototype.say=function(){
console.log(this.種類(lèi)+"叫");
}
var animal=new Animal();
animal.say();
var Cat=function(){
Animal.apply(this,arguments);
this.tail="一條尾巴";
}
//下面三句是為了實(shí)現(xiàn):Cat.prototype._proto_=Animal.prototype;只是Cat.prototype._proto_為ES6,IE低版本不支持
var F=function(){}; //創(chuàng)建新的對(duì)象
F.prototype=Animal.prototype; //將新對(duì)象的prototype指向Animal
Cat.prototype=new F(); //讓Cat.prototype的_proto_指向F的prototype,此時(shí)的Cat也是一個(gè)構(gòu)造函數(shù),因?yàn)椴皇荂at=new F();
var cat=new Cat();
cat.constructor==Animal //true,表示cat的構(gòu)造函數(shù)是Animal
Cat.prototype.constructor=Cat; //把構(gòu)造函數(shù)指向Cat
4、不用類(lèi)實(shí)現(xiàn)繼承
var animal={
"種類(lèi)":"動(dòng)物",
say:function(){
console.log("叫");
}
}
var cat=extend(animal); //使用任意手段讓cat._proto_指向animal
function extend(parent){
var Temp=function(){};
Temp.prototype=parent;
return new Temp;
}
cat.tail="一條尾巴";
cat.say=function(){
console.log("喵喵喵");
}
5、代碼封裝的演變
-
把代碼用對(duì)象包住,避免全局污染
缺點(diǎn):只在當(dāng)前頁(yè)面對(duì)一個(gè)代碼實(shí)現(xiàn)功能,要在當(dāng)前頁(yè)面的兩個(gè)地方實(shí)現(xiàn)代碼,慎用
var Tab={
init: function(){ //把變量全部放到init方法中,并設(shè)置初始值。
this.name="Ethan";
this.bind(); //執(zhí)行bind方法
}
bind: function(){
this.name //調(diào)用name變量要在前面加上this,并確保this指的是Tab
var self=this; //若this的指向會(huì)變,那在改變前先把當(dāng)前this進(jìn)行保存,在進(jìn)行引用
self.name;
}
}
Tab.init();
-
通過(guò)new方法創(chuàng)建獨(dú)立的對(duì)象
優(yōu)點(diǎn):可以對(duì)功能進(jìn)行重復(fù)使用,缺點(diǎn):構(gòu)造函數(shù)里的方法重復(fù)創(chuàng)建
function Tab(tagName){
this.init=function(tagName){
this.name="Ethan";
}
this.bind=function(){
this.name //調(diào)用name變量要在前面加上this,并確保this指的是Tab
var self=this; //若this的指向會(huì)變,那在改變前先把當(dāng)前this進(jìn)行保存,在進(jìn)行引用
self.name;
}
this.init(tagName);
this.bind(); //執(zhí)行bind方法
}
var tagName1=document.getElementsByClassName("class1")[0];
var tagName2=document.getElementsByClassName("class2")[0];
new Tag(tagName1);
new Tag(tagName2);
-
給new方法創(chuàng)建的對(duì)象設(shè)立原型
優(yōu)點(diǎn):把方法全部放進(jìn)原型當(dāng)中,使用new方法時(shí)創(chuàng)建的實(shí)例就不會(huì)再創(chuàng)建方法,直接從原型鏈中找,節(jié)省了空間
function Tab(tagName){
this.init(tagName);
this.bind(); //執(zhí)行bind方法
}
Tab.prototype.init=function(tagName){
this.name="Ethan";
}
Tab.prototype.bind=function(){
this.name //調(diào)用name變量要在前面加上this,并確保this指的是Tab
var self=this; //若this的指向會(huì)變,那在改變前先把當(dāng)前this進(jìn)行保存,在進(jìn)行引用
self.name;
}
var tagName1=document.getElementsByClassName("class1")[0];
var tagName2=document.getElementsByClassName("class2")[0];
new Tag(tagName1);
new Tag(tagName2);