Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
編寫程序時,我們經常需要重復執行某些操作,這時候循環結構就顯得非常有用。JavaScript 提供了多種循環結構,以適應不同的編程場景。以下是 JavaScript 中常見的循環結構:
for 循環是最常見的循環結構之一,它允許我們指定循環開始前的初始化代碼、循環繼續的條件以及每次循環結束時要執行的代碼。
for (初始化表達式; 循環條件; 循環后的操作表達式) {
// 循環體代碼
}
for (var i=1; i <=10; i++) {
console.log(i);
}
while 循環在給定條件為真時將不斷循環執行代碼塊。與 for 循環不同,while 循環只有循環條件,沒有初始化和迭代表達式。
while (條件) {
// 循環體代碼
}
var i=1;
while (i <=10) {
console.log(i);
i++;
}
do...while 循環和 while 循環類似,但它至少會執行一次循環體,無論條件是否為真。
do {
// 循環體代碼
} while (條件);
var i=1;
do {
console.log(i);
i++;
} while (i <=10);
for...in 循環用于遍歷對象的屬性。
for (var key in 對象) {
// 使用 key 訪問對象屬性
}
var person={
name: "張三",
age: 30,
job: "軟件工程師"
};
for (var key in person) {
console.log(key + ": " + person[key]);
}
for...of 循環用于遍歷可迭代對象(如數組、字符串等)的元素。
for (var item of 可迭代對象) {
// 使用 item 訪問元素
}
var fruits=["蘋果", "香蕉", "橘子"];
for (var fruit of fruits) {
console.log(fruit);
}
JavaScript 的循環結構為我們提供了強大的工具來處理重復任務。for 循環適合于當我們知道循環次數時使用;while 和 do...while 循環適合于循環次數未知,但是循環條件明確的情況;for...in 和 for...of 循環則讓對象和數組的遍歷變得更加簡潔。掌握這些循環結構有助于我們編寫更加高效和可讀性更強的代碼。
件語句的代碼可以被想象成是一條條分支的路徑,而循環語句的代碼則是程序路徑的一個回路,可以讓一部分代碼重復執行。JavaScript中的循環語句有for語句和while語句。
for語句的語法如下:
1 for(初始值;布爾值;計數器){
2 //語句塊
3 }
在for語句中,如果布爾值是true,就會一直執行語句塊中的內容,為了防止死循環,需要有一個計數器,當數值達到指定值,布爾值就會變成false,循環便停止了,下面的示例代碼使用for循環輸出0~9九個數字示例代碼如下:
1 for(var i=0;i<10;i++){
2 // i的初始值是0
3 // 判斷i是否小于10,如果小于10則執行花括號中的代碼
4 // 每次執行完花括號中的代碼后,i的值加1
5 console.log(i);
6 }
通過上面的例子我們進一步理解了for語句的用法,下面我們來做一個聯系,利用for循環語句輸出100以內所有正整數的加和示例代碼如下:
1 var sum=0; //sum用來存儲循環過程中正整數的加和
2 for(var i=1;i<=100;i++){
3 sum +=i;
4 }
5 console.log(sum); //這時候輸出的就應該是5050
while語句語法如下所示:
1 while(bool){
2 //bool為true,循環執行
3 }
當bool為true的時候,花括號中的內容會循環執行。為了防止死循環,需要在循環的過程實現類似for計數器的功能,讓循環在有限的次數內定制,下面我們使用while語句輸出0~9是個數字示例代碼如下:
1 var n=0;
2 while(n<10){
3 console.log(n);
4 n++;
5 }
在每次循環的過程中都會讓n的值加1,這樣當n的值等于10,循環便停止,下面我來使用while語句輸出100以內所有正整數的加和示例代碼如下:
1 var n=0;
2 var sum=0;
3 while(n<=100){
4 sum +=n;
5 n++;
6 }
7 console.log(sum);
continue可以結束本次循環,直接進入到下一次循環,例如我們用for循環語句來實現輸出0 ~ 5,7 ~ 9九個數字(跳過6)示例代碼如下:
1 for(var i=0;i<10;i++){
2 if(i===6){
3 continue;
4 }
5 console.log(i);
6 }
上面的代碼通過判斷,實現當i的值為6的時候,跳過本次循環,直接接入下一次循環。下面我們使用continue來實現計算100以內所有不能被7整除的正整數加和示例代碼如下:
1 var sum=0;
2 for(var i=0;i<=100;i++){
3 if(i%7===0){
4 continue;
5 }
6 sum +=i;
7 }
8 console.log(sum);
在學switch語句中,我們已經接觸到了break,它可以讓分支語句在結束一個case之后,跳出switch語句,break同樣可以用在循環語句當中,當代碼執行到break時,直接結束循環示例代碼如下:
1 for(var i=0;i<10;i++){
2 if(i===6){
3 break;
4 }
5 console.log(i);
6 }
如上面的代碼所示,當控制帶輸出5之后,循環結束。
【融職教育】在工作中學習,在學習中工作
wift 使用自動引用計數(ARC)這一機制來跟蹤和管理應用程序的內存
通常情況下我們不需要去手動釋放內存,因為 ARC 會在類的實例不再被使用時,自動釋放其占用的內存。
但在有些時候我們還是需要在代碼中實現內存管理。
ARC 功能
當每次使用 init() 方法創建一個類的新的實例的時候,ARC 會分配一大塊內存用來儲存實例的信息。
內存中會包含實例的類型信息,以及這個實例所有相關屬性的值。
當實例不再被使用時,ARC 釋放實例所占用的內存,并讓釋放的內存能挪作他用。
為了確保使用中的實例不會被銷毀,ARC 會跟蹤和計算每一個實例正在被多少屬性,常量和變量所引用。
實例賦值給屬性、常量或變量,它們都會創建此實例的強引用,只要強引用還在,實例是不允許被銷毀的。
ARC 實例
class Person { let name: String init(name: String) { self.name=name print("\(name) 開始初始化") } deinit { print("\(name) 被析構") }}// 值會被自動初始化為nil,目前還不會引用到Person類的實例var reference1: Person?var reference2: Person?var reference3: Person?// 創建Person類的新實例reference1=Person(name: "Runoob")//賦值給其他兩個變量,該實例又會多出兩個強引用reference2=reference1 reference3=reference1//斷開第一個強引用reference1=nil//斷開第二個強引用reference2=nil//斷開第三個強引用,并調用析構函數reference3=nil
以上程序執行輸出結果為:
Runoob 開始初始化Runoob 被析構
類實例之間的循環強引用
在上面的例子中,ARC 會跟蹤你所新創建的 Person 實例的引用數量,并且會在 Person 實例不再被需要時銷毀它。
然而,我們可能會寫出這樣的代碼,一個類永遠不會有0個強引用。這種情況發生在兩個類實例互相保持對方的強引用,并讓對方不被銷毀。這就是所謂的循環強引用。
實例
下面展示了一個不經意產生循環強引用的例子。例子定義了兩個類:Person和Apartment,用來建模公寓和它其中的居民:
class Person { let name: String init(name: String) { self.name=name } var apartment: Apartment? deinit { print("\(name) 被析構") }}class Apartment { let number: Int init(number: Int) { self.number=number } var tenant: Person? deinit { print("Apartment #\(number) 被析構") }}// 兩個變量都被初始化為nilvar runoob: Person?var number73: Apartment?// 賦值runoob=Person(name: "Runoob")number73=Apartment(number: 73)// 意感嘆號是用來展開和訪問可選變量 runoob 和 number73 中的實例// 循環強引用被創建runoob!.apartment=number73 number73!.tenant=runoob// 斷開 runoob 和 number73 變量所持有的強引用時,引用計數并不會降為 0,實例也不會被 ARC 銷毀// 注意,當你把這兩個變量設為nil時,沒有任何一個析構函數被調用。// 強引用循環阻止了Person和Apartment類實例的銷毀,并在你的應用程序中造成了內存泄漏runoob=nilnumber73=nil
解決實例之間的循環強引用
Swift 提供了兩種辦法用來解決你在使用類的屬性時所遇到的循環強引用問題:
弱引用
無主引用
弱引用和無主引用允許循環引用中的一個實例引用另外一個實例而不保持強引用。這樣實例能夠互相引用而不產生循環強引用。
對于生命周期中會變為nil的實例使用弱引用。相反的,對于初始化賦值后再也不會被賦值為nil的實例,使用無主引用。
弱引用實例
class Module { let name: String init(name: String) { self.name=name } var sub: SubModule? deinit { print("\(name) 主模塊") }}class SubModule { let number: Int init(number: Int) { self.number=number } weak var topic: Module? deinit { print("子模塊 topic 數為 \(number)") }}var toc: Module?var list: SubModule?toc=Module(name: "ARC")list=SubModule(number: 4)toc!.sub=list list!.topic=toc toc=nillist=nil
以上程序執行輸出結果為:
ARC 主模塊子模塊 topic 數為 4
無主引用實例
class Student { let name: String var section: Marks? init(name: String) { self.name=name } deinit { print("\(name)") }}class Marks { let marks: Int unowned let stname: Student init(marks: Int, stname: Student) { self.marks=marks self.stname=stname } deinit { print("學生的分數為 \(marks)") }}var module: Student?module=Student(name: "ARC")module!.section=Marks(marks: 98, stname: module!)module=nil
以上程序執行輸出結果為:
ARC學生的分數為 98
閉包引起的循環強引用
循環強引用還會發生在當你將一個閉包賦值給類實例的某個屬性,并且這個閉包體中又使用了實例。這個閉包體中可能訪問了實例的某個屬性,例如self.someProperty,或者閉包中調用了實例的某個方法,例如self.someMethod。這兩種情況都導致了閉包 "捕獲" self,從而產生了循環強引用。
實例
下面的例子為你展示了當一個閉包引用了self后是如何產生一個循環強引用的。例子中定義了一個叫HTMLElement的類,用一種簡單的模型表示 HTML 中的一個單獨的元素:
class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String={ if let text=self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String?=nil) { self.name=name self.text=text } deinit { print("\(name) is being deinitialized") } }// 創建實例并打印信息var paragraph: HTMLElement?=HTMLElement(name: "p", text: "hello, world")print(paragraph!.asHTML())
HTMLElement 類產生了類實例和 asHTML 默認值的閉包之間的循環強引用。
實例的 asHTML 屬性持有閉包的強引用。但是,閉包在其閉包體內使用了self(引用了self.name和self.text),因此閉包捕獲了self,這意味著閉包又反過來持有了HTMLElement實例的強引用。這樣兩個對象就產生了循環強引用。
解決閉包引起的循環強引用:在定義閉包時同時定義捕獲列表作為閉包的一部分,通過這種方式可以解決閉包和類實例之間的循環強引用。
弱引用和無主引用
當閉包和捕獲的實例總是互相引用時并且總是同時銷毀時,將閉包內的捕獲定義為無主引用。
相反的,當捕獲引用有時可能會是nil時,將閉包內的捕獲定義為弱引用。
如果捕獲的引用絕對不會置為nil,應該用無主引用,而不是弱引用。
實例
前面的HTMLElement例子中,無主引用是正確的解決循環強引用的方法。這樣編寫HTMLElement類來避免循環強引用:
class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String={ [unowned self] in if let text=self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String?=nil) { self.name=name self.text=text } deinit { print("\(name) 被析構") } }//創建并打印HTMLElement實例var paragraph: HTMLElement?=HTMLElement(name: "p", text: "hello, world")print(paragraph!.asHTML())// HTMLElement實例將會被銷毀,并能看到它的析構函數打印出的消息paragraph=nil
以上程序執行輸出結果為:
<p>hello, world</p>p 被析構
*請認真填寫需求信息,我們會在24小時內與您取得聯系。