問題1: OOP 指什么晴圾?有哪些特性
-
OOP:
“面向?qū)ο缶幊獭保∣bject Oriented Programming)是目前主流的編程范式。Java,JavaScript趁桃,C#,C+ +,Python卫病,PHP油啤,Ruby和Objective-C)都支持面向?qū)ο缶幊獭K暮诵乃枷胧菍⒄鎸嵤澜缰懈鞣N復(fù)雜的關(guān)系蟀苛,抽象為一個個對象益咬,然后由對象之間的分工與合作,完成對真實世界的模擬帜平。每個對象都可以被看作是一個擁有清晰角色或責任的獨立小機器幽告。
“傳統(tǒng)的過程式編程”(procedural programming)由一系列函數(shù)或一系列指令組成,而面向?qū)ο缶幊痰某绦蛴梢幌盗袑ο蠼M成裆甩。每一個對象都是功能中心冗锁,具有明確分工,可以完成接受信息嗤栓、處理數(shù)據(jù)冻河、發(fā)出信息等任務(wù)。因此抛腕,面向?qū)ο缶幊叹哂徐`活性芋绸、代碼的可重用性、模塊性等特點担敌,容易維護和開發(fā)摔敛,非常適合多人合作的大型軟件項目。 -
特性:
封裝性全封,繼承性马昙,多態(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();
//封裝性:把相對應(yīng)的變量和方法封裝到一起
//繼承性:ethan實例對象本身沒有定義sayHello,但是由于ethan是構(gòu)造函數(shù)Person的實例刹悴,繼承Person存放在prototype對象中的共有屬性和方法行楞,所以可以調(diào)用sayHello。
//多態(tài)性:同一個方法可以有不同的表現(xiàn)土匀。比如通過new兩個實例子房,可以分別對里面的方法函數(shù)擴展,得到的結(jié)果不同就轧,但是证杭,這都屬于同一個方法。
問題2: 如何通過構(gòu)造函數(shù)的方式創(chuàng)建一個擁有屬性和方法的對象?
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
問題3: prototype 是什么妒御?有什么特性
JavaScript 的每個對象都繼承另一個對象解愤,后者稱為“原型”(prototype)對象。只有null除外乎莉,它沒有自己的原型對象送讲。
原型對象上的所有屬性和方法奸笤,都能被派生對象共享。這就是 JavaScript 繼承機制的基本設(shè)計哼鬓。
通過構(gòu)造函數(shù)生成實例對象時监右,會自動為實例對象分配原型對象。每一個構(gòu)造函數(shù)都有一個prototype屬性异希,這個屬性就是實例對象的原型對象秸侣。
var Person = function (name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('hello');
}
var ethan = new Person('ethan');
ethan.sayHello();
//其中Person的prototype對象,就是ethan的原型對象宠互。ethan.sayHello先在實例當中找方法,若沒找到椭坚,就去prototype對象中找予跌。
ethan.sayHello=function(){
console.log("hi");
}
ethan.sayHello();
//因為ethan實例當中已經(jīng)有sayHello方法,所以不會再去原型上找方法
問題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: 創(chuàng)建一個 Car 對象善茎,擁有屬性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(){...};
}
問題6: 創(chuàng)建一個 GoTop 對象耕赘,當 new 一個 GotTop 對象則會在頁面上創(chuàng)建一個回到頂部的元素骄蝇,點擊頁面滾動到頂部。擁有以下屬性和方法
1. `ct`屬性操骡,GoTop 對應(yīng)的 DOM 元素的容器
2. `target`屬性九火, GoTop 對應(yīng)的 DOM 元素
3. `bindEvent` 方法, 用于綁定事件
4 `createNode` 方法册招, 用于在容器內(nèi)創(chuàng)建節(jié)點
問題7: 使用木桶布局實現(xiàn)一個圖片墻
筆記:
1岔激、 面向?qū)ο蟮某跣?/h6>
- 目的
1、改善可讀性
screenprint();
Screen.print();
2是掰、提升重用性
1、改善可讀性
screenprint();
Screen.print();
2是掰、提升重用性
2虑鼎、原則:開放封閉原則
1、對于擴展是開放的(open for extension)键痛。當應(yīng)用的需求改變時炫彩,可以對模塊進行擴展,使其滿足改變的新行為散休。
2媒楼、 對于修改是關(guān)閉的(close for modification)。對模塊進行擴展時戚丸,不必改變模塊的源代碼划址。
3扔嵌、三要素:封裝,繼承夺颤,多態(tài)
1痢缎、封裝:把很多個屬性和方法封裝到一個對象當中
2、繼承:繼承一個對象的所有的屬性和方法
3世澜、多態(tài):不同的對象對同一個方法有不同的表現(xiàn)
4独旷、實例化對象
var object=new Object();
2、 new操作
var object=new Object()時寥裂,都發(fā)生了什么嵌洼?
1、創(chuàng)建了一個空對象作為this
2封恰、this.proto指向構(gòu)造函數(shù)的prototype
3麻养、運行構(gòu)造函數(shù)
4、返回this(如果構(gòu)造函數(shù)里沒有return诺舔,若存在return引用類型鳖昌,則返回return后的值)
var Foo=function(){
this.name="foo";
}
var foo=new Foo();
console.log(foo); //console.log(),console對象時低飒,先展示對象的構(gòu)造函數(shù)
//發(fā)生了什么许昨?
1、創(chuàng)建了{}褥赊,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對象時司光,先展示對象的構(gòu)造函數(shù)
//發(fā)生了什么琅坡?
1、創(chuàng)建了{}残家,this指向{}
2榆俺、{}._proto_指向了Foo.prototype
3、執(zhí)行構(gòu)造函數(shù)坞淮,{}.name="foo"
4茴晋、返回{name:"foo1"}
3、如何手動指定對象原型
//第一種:
var obj._proto_={...}; //ES6方法支持._proto_屬性回窘,IE低版本不支持
//第二種:
var my={
name:"foo"
}
var obj={};
var Temp=functon(){};
Temp.prototype=my;
obj=new Temp(); //此時的constructor指向的是Temp
obj.constructor=my;
var Animal=function(){
this.種類="動物";
}
Animal.prototype.say=function(){
console.log(this.種類+"叫");
}
var animal=new Animal();
animal.say();
var Cat=function(){
Animal.apply(this,arguments);
this.tail="一條尾巴"诺擅;
}
//下面三句是為了實現(xiàn):Cat.prototype._proto_=Animal.prototype;只是Cat.prototype._proto_為ES6,IE低版本不支持
var F=function(){}; //創(chuàng)建新的對象
F.prototype=Animal.prototype; //將新對象的prototype指向Animal
Cat.prototype=new F(); //讓Cat.prototype的_proto_指向F的prototype啡直,此時的Cat也是一個構(gòu)造函數(shù)烁涌,因為不是Cat=new F();
var cat=new Cat();
cat.constructor==Animal //true苍碟,表示cat的構(gòu)造函數(shù)是Animal
Cat.prototype.constructor=Cat; //把構(gòu)造函數(shù)指向Cat
4、不用類實現(xiàn)繼承
var animal={
"種類":"動物"撮执,
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微峰、代碼封裝的演變
-
把代碼用對象包住,避免全局污染
缺點:只在當前頁面對一個代碼實現(xiàn)功能抒钱,要在當前頁面的兩個地方實現(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的指向會變仗扬,那在改變前先把當前this進行保存,在進行引用
self.name;
}
}
Tab.init();
-
通過new方法創(chuàng)建獨立的對象
優(yōu)點:可以對功能進行重復(fù)使用蕾额,缺點:構(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的指向會變厉颤,那在改變前先把當前this進行保存,在進行引用
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)建的對象設(shè)立原型
優(yōu)點:把方法全部放進原型當中凡简,使用new方法時創(chuàng)建的實例就不會再創(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的指向會變秤涩,那在改變前先把當前this進行保存,在進行引用
self.name;
}
var tagName1=document.getElementsByClassName("class1")[0];
var tagName2=document.getElementsByClassName("class2")[0];
new Tag(tagName1);
new Tag(tagName2);