面向過程
對象的創建
在js中,對象的創建有兩種方式
- new Object()
- {}
通過上述的兩種方式,都可以創建一個空的對象
var obj1 = new Object();
console.log(obj1);
var obj2 = {};
console.log(obj2);
//打印的都是一個空對象
這時,我們通過在一個空的對象上添加特征來擴展我們想要的對象類型
var obj3 = new Object();
obj3.name = "小明";
obj3.gender = "男";
obj3.age = 18;
console.log(obj3);
//打印的就是帶著不同屬性和值的對象
在實際開發中,我們可能會創建很多相同特征(類型)的對象,那么我們會把創建相同特征的對象的過程進行封裝
function creat(name,gender,age){
var obj = new Object();
obj3.name = name;
obj3.gender = gender;
obj3.age = age;
return obj;
}
//在使用時通過傳參來創建不同的對象
var obj1 = creat("小明","男",18);
var obj2 = creat("小紅","女",28);
new
new是運算符的一種,通過new運算符運算函數,會得到一個對象的結果,new只能和函數配合使用,new只能和函數配合使用,像new Data(),new Object(),new Arr()等等一些常用的都是我們瀏覽器里的js解析器自帶的函數,只是把創建特征過程沒有展示出來給我們看到,我們使用的時候相當于調用了這個方法
那當我們通過new的方式去調用執行一個函數的時候
- 在函數內部自動創建一個空的對象
- 把該函數的this指向該對象
- 函數執行完成自動返回該對象
function fn(){
console.log(this);
}
var f1 = fn(); //執行了,打印this這個時候指向window this->window
console.log(f1); //f1是個fn執行后,沒有返回值,打印是undefind
var f2 = new fn;
//直接通過new來運算執行函數,可以不加() this-> Object 指向fn內部自動創建的一個空對象
var f3 = new fn();
console.log(f2); //打印的是fn {};
console.log(f3); //打印的是fn {}
//通過new來執行一個函數的時候,如果該函數不需要傳入任何參數,我們可以省略(),如果不傳入任何參數,()也是可以帶的,
當我們通過new的方式去調用執行一個函數的時候,返回:
如果沒有return,返回內部創建的空對象
-
如果有return
- return的是非對象,返回內部創建的空對象
- return的是對象,返回就是return的對象
function fn2(){ return 1; } var r1 = fn2(); console.log(r1); //1 var r2 = new fn2(); console.log(r2); //內部創建的空對象 ==> this ***** function fn3(){ return {x: 100,y: 200}; } var r3 = fn3(); console.log(fn3); //函數return的對象 var r4 = fn3(); console.log(fn4); //函數return的對象
new構造函數的一些注意事項
構造函數 <-> 類
類: 類型,對具有相同特征的對象的抽象描述
對象: 由類創建出來的具體對象(實例),也稱為實例化對象
構造函數: 類中用來創建對象的具體函數,類創建對象的時候調用的初始化函數
function Creat(name,gender,age) {
this.name = name;
this.gender = gender;
this.age = age;
this.fn = funciton(){
cosole.log("我是fn函數")
}
this.fn2 = fn2;
}
function fn2(){
cosole.log("我是fn2函數")
}
var obj1 = new Creat("小明","男",18);
obj1.fn(); //我是fn函數
console.log(obj1); //Object
var obj2 = new Creat("小紅","女",28);
obj2.fn(); //我是fn函數
console.log(obj2); //Object
console.log(obj1.fn == obj2.fn) //false
console.log(obj1.fn2 == obj2.fn2) //true
通過Creat構造函數創建出來了下面兩個對象,這兩個對象都擁有相同的特征,不同的對象相同的特征也會有不同的值,每一個對象都擁有屬于自己的特征值,但是有時候,對象的一些特征所擁有的值其實也是一樣,那么如果每個對象對這樣的相同值的特征也是獨立保存一份的話,就會照成資源浪費(內存占用),所以我們需要去優化這個問題。
原型,原型鏈
為了使對象共有的特征方法維護和管理,所以有一種專門來管理和維護這些共同特征的方法(手段)
當一個函數被創建的時候,該函數下自動會有一些屬性(函數也是對象),其中有一個屬性,名稱:prototype,他的值是一個對象,我們通常就把構造函數創建的對象所擁有的共同特征保存在這些對象的構造函數的prototype屬性下,\
當一個對象被創建的時候,對象自動會創建一個屬性,名稱:proto,該屬性也是一個對象,其實該屬性就是該對象的構造函數的prototype
當我們去調用一個對象下的屬性或方法的時候,對象首先會在自身上查找是否該屬性或方法,如果有則調用,如果沒有,則會查找自己的proto屬性上是否有給屬性或方法
總結:
- 我們通常把對象私有屬性或方法放置在每個對象自身上
- 我們通常把對象公有(共有)的屬性或方法放置在這些對象的構造函數的原型下
function Creat(name,gender,age) {
this.name = name;
this.gender = gender;
this.age = age;
this.fn = funciton(){
cosole.log("我是fn函數")
}
}
Creat.prototype.fn2 = funciton(){
cosole.log("我是fn2函數")
}
var obj1 = new Creat("小明","男",18)
//obj1的__proto__ 其實就是 Creat.prototype
console.log(obj1.__proto__ == Creat.prototype); //true
obj1.fn(); //自己有,直接調用
obj1.fn2(); //自己沒有,去看下自己下面的__proto__
var obj2 = new Creat("小紅","女",28);
console.log(obj1.fn == obj2.fn); //false
console.log(obj1.fn2 == obj2.fn2); //true
*/這樣沒創建一個新的對象時,就不用在給每個添加一個單獨的fn屬性,只用在構造函數下的prototype下添加可以共用的函數,在它下面調用
面向對象例子
拖拽:
<div id="div1"></div>
<style>
#div {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 200px;
}
</style>
var div1 = document.querySelector("#div1");
function Drag(elment){
this.elment = elment;
this.disX = 0;
this.disY = 0;
var _this = this; //記錄this指向是Drop
this.elment.onmousedown = function(e){
_this.down(e);
//這里如果是this的話,就是找的執行mousedown這個元素了,它下面沒有down這個對象,所以上面要記錄下_this
document.onmousemove = function(e){
_this.move(e)
}
document.onmouseup = function(){
_this.end();
}
}
}
Drag.prototype.down = function(e){ //傳執行時的event
console.log(this)
this.disX = e.clientX - this.elment.offsetLeft; //this => Drop
this.disX = e.clientX - this.elment.offsetLeft;
}
Drag.prototype.move = function(e){
this.elment.style.left = e.clientX - this.disX + 'px';
this.elment.style.top = e.clientY - this.disY + 'px';
}
Drag.prototype.end = function(e){
document.onmousemove = document.onmouseup = null;
}
new Drag(div1); //調用記得加new