1. JS中的面向物件
創建物件的幾種常用方法:
1.使用Object或物件字面量創建物件
2.工廠模式創建物件
3.建構式模式創建物件
4.原型模式創建物件
1.1 使用Object或物件字面量創建物件
JS中最基本創建物件的方式:
var student = new Object(); student.name = "easy"; student.age = "20";
這樣,一個student物件就創建完畢,擁有2個屬性name以及age,分別賦值為"easy"和20,
如果你嫌這種方法有一種封裝性不良的感覺,來一個物件字面量方式創建物件,
var sutdent = { name : "easy", age : 20 };
這樣看起來似乎就完美了,但是馬上我們就會發現一個十分尖銳的問題:當我們要創建同類的student1,student2,…,studentn時,我們不得不將以上的代碼重復n次,
var sutdent1 = { name : "easy1", age : 20 }; var sutdent2 = { name : "easy2", age : 20 }; ... var sutdentn = { name : "easyn", age : 20 };
有個提問?能不能像工廠車間那樣,有一個車床就不斷生產出物件呢?我們看”工廠模式”,
1.2 工廠模式創建物件
JS中沒有類的概念,那么我們不妨就使用一種函式將以上物件創建程序封裝起來以便于重復呼叫,同時可以給出特定介面來初始化物件,
function createStudent(name, age) { var obj = new Object(); obj.name = name; obj.age = age; return obj; } var student1 = createStudent("easy1", 20); var student2 = createStudent("easy2", 20); ... var studentn = createStudent("easyn", 20);
這樣一來我們就可以通過createStudent函式源源不斷地”生產”物件了,看起來已經高枕無憂了,但貪婪的人類總有不滿足于現狀的天性:我們不僅希望”產品”的生產可以像工廠車間一般源源不斷,我們還想知道生產的產品究竟是哪一種型別的,
比如說,我們同時又定義了”生產”水果物件的createFruit()函式:
function createFruit(name, color) { var obj = new Object(); obj.name = name; obj.color = color; return obj; } var v1 = createStudent("easy1", 20); var v2 = createFruit("apple", "green");
對于以上代碼創建的物件v1、v2,我們用instanceof運算子去檢測,他們統統都是Object型別,我們的當然不滿足于此,我們希望v1是Student型別的,而v2是Fruit型別的,為了實作這個目標,我們可以用自定義建構式的方法來創建物件,
1.3 建構式模式創建物件
在上面創建Object這樣的原生物件的時候,我們就使用過其建構式:
var obj = new Object();
在創建原生陣列Array型別物件時也使用過其建構式:
var arr = new Array(10); //構造一個初始長度為10的陣列物件
在進行自定義建構式創建物件之前,我們首先了解一下建構式和普通函式有什么區別,
1、實際上并不存在創建建構式的特殊語法,其與普通函式唯一的區別在于呼叫方法,對于任意函式,使用new運算子呼叫,那么它就是建構式;不使用new運算子呼叫,那么它就是普通函式,
2、按照慣例,我們約定建構式名以大寫字母開頭,普通函式以小寫字母開頭,這樣有利于顯性區分二者,例如上面的new Array(),new Object(),
3、使用new運算子呼叫建構式時,會經歷(1)創建一個新物件;(2)將建構式作用域賦給新物件(使this指向該新物件);(3)執行建構式代碼;(4)回傳新物件;4個階段,
了解了建構式和普通函式的區別之后,我們使用建構式將工廠模式的函式重寫,并添加一個方法屬性:
function Student(name, age) { this.name = name; this.age = age; this.alertName = function(){ alert(this.name) }; } function Fruit(name, color) { this.name = name; this.color = color; this.alertName = function(){ alert(this.name) }; }
這樣我們再分別創建Student和Fruit的物件:
var v1 = new Student("easy", 20); var v2 = new Fruit("apple", "green");
這時我們再來用instanceof運算子來檢測以上物件型別就可以區分出Student以及Fruit了:
alert(v1 instanceof Student); //true alert(v2 instanceof Student); //false alert(v1 instanceof Fruit); //false alert(v2 instanceof Fruit); //true alert(v1 instanceof Object); //true 任何物件均繼承自Object alert(v2 instanceof Object); //true 任何物件均繼承自Object
這樣我們就解決了工廠模式無法區分物件型別的尷尬,那么使用構造方法來創建物件是否已經完美了呢?使用構造器函式通常在js中我們來創建物件,
我們會發現Student和Fruit物件中共有同樣的方法,當我們進行呼叫的時候這無疑是記憶體的消耗,
我們完全可以在執行該函式的時候再這樣做,辦法是將物件方法移到建構式外部:
function Student(name, age) { this.name = name; this.age = age; this.alertName = alertName; } function alertName() { alert(this.name); } var stu1 = new Student("easy1", 20); var stu2 = new Student("easy2", 20);
在呼叫stu1.alertName()時,this物件才被系結到stu1上,
我們通過將alertName()函式定義為全域函式,這樣物件中的alertName屬性則被設定為指向該全域函式的指標,由此stu1和stu2共享了該全域函式,解決了記憶體浪費的問題
但是,通過全域函式的方式解決物件內部共享的問題,終究不像一個好的解決方法,如果這樣定義的全域函式多了,我們想要將自定義物件封裝的初衷便幾乎無法實作了,更好的方案是通過原型物件模式來解決,
1.4 原型的模式創建物件
原型鏈甚至原型繼承,是整個JS中最難的一部分也是最不好理解的一部分,在這里由于我們課程定位的原因,如果對js有興趣的同學,可以去查閱一下相關JS原型的一些知識點,更加有助于你以后前端JS的面試,
function Student() { this.name = 'easy'; this.age = 20; } Student.prototype.alertName = function(){ alert(this.name); }; var stu1 = new Student(); var stu2 = new Student(); stu1.alertName(); //easy stu2.alertName(); //easy alert(stu1.alertName == stu2.alertName); //true 二者共享同一函式
2. 定時器
在js中的定時器分兩種:1、setTimeout() 2、setInterval(),
2.1 setTimeOut()
只在指定時間后執行一次
/定時器 異步運行 function hello(){ alert("hello"); } //使用方法名字執行方法 var t1 = window.setTimeout(hello,1000); var t2 = window.setTimeout("hello()",3000);//使用字串執行方法 window.clearTimeout(t1);//去掉定時器
2.2 setInterval()
在指定時間為周期回圈執行
/實時重繪 時間單位為毫秒
setInterval('refreshQuery()',8000);
/* 重繪查詢 */
function refreshQuery(){
console.log('每8秒調一次')
}
兩種方法根據不同的場景和業務需求擇而取之,
對于這兩個方法,需要注意的是如果要求在每隔一個固定的時間間隔后就精確地執行某動作,那么最好使用setInterval,而如果不想由于連續呼叫產生互相干擾的問題,尤其是每次函式的呼叫需要繁重的計算以及很長的處理時間,那么最好使用setTimeout,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/170812.html
標籤:JavaScript
