中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

求推薦公司網(wǎng)站建設品牌推廣思路

求推薦公司網(wǎng)站建設,品牌推廣思路,優(yōu)設設計網(wǎng)站導航,wordpress改微博系統(tǒng)在眾多的編程語言中, JavaScript 給大部分的人的第一印象是人畜無害,看起來就簡單的,對稍微有點兒開發(fā)經(jīng)驗的人來說,在網(wǎng)頁中寫個JavaScript功能也相當簡單。但是當你真的得了解了JavaScript之后就會發(fā)現(xiàn),它比我們想象…

在眾多的編程語言中, JavaScript 給大部分的人的第一印象是人畜無害,看起來就簡單的,對稍微有點兒開發(fā)經(jīng)驗的人來說,在網(wǎng)頁中寫個JavaScript功能也相當簡單。但是當你真的得了解了JavaScript之后就會發(fā)現(xiàn),它比我們想象中強大復雜的多。

也是因為 JavaScript 的復雜和細致讓他很容易就出問題。我們就今天就準備討論一下,在前端開發(fā)中的10個常見的問題。

時至今日JavaScript 幾乎成為了所有現(xiàn)代 Web 應用的核心。而把JavaScript研究明白,找到JavaScript出問題的原因也就成了一名合格前端的首要任務。

基于 JavaScript 的強大庫和框架,用于單頁應用程序(SPA)開發(fā)、圖形和動畫、以及服務器端 JavaScript 平臺,這些并不是什么新鮮事兒。JavaScript 已經(jīng)成為 Web 應用程序開發(fā)領域中無處不在的語言,因此掌握 JavaScript 成為了一個日益重要的技能。

一、不正確的引用this

隨著JavaScript的日益發(fā)展,編碼技術和設計模式越來越復雜,回調和閉包中的自引用作用域也相應增加。在我們日常開發(fā)中一定的會遇到"this/that 混亂 "的問題。

考慮下面代碼:

Game.prototype.restart = function () {    this.clearLocalStorage();    this.timer = setTimeout(function() {    this.clearBoard();    // What is "this"?    }, 0);};

執(zhí)行上述代碼會出現(xiàn)以下錯誤:

Uncaught?TypeError:?undefined?is?not?a?function

上述錯誤的原因是,當調用 setTimeout()時,實際上是在調用 window.setTimeout()。因此,傳遞給setTimeout()的匿名函數(shù)是在window對象的上下文中定義的,它沒有clearBoard()方法。

傳統(tǒng)的、符合老式瀏覽器的解決方案是將 this 引用保存在一個變量中,然后可以被閉包繼承,如下所示:???????

Game.prototype.restart = function () {    this.clearLocalStorage();    var self = this;   // Save reference to 'this', while it's still this!    this.timer = setTimeout(function(){    self.clearBoard();    // Oh OK, I do know who 'self' is!    }, 0);};

另外,在較新的瀏覽器中,可以使用bind()方法來傳入適當?shù)囊?#xff1a;

???????

Game.prototype.restart = function () {    this.clearLocalStorage();    this.timer = setTimeout(this.reset.bind(this), 0);  // Bind to 'this'};
Game.prototype.reset = function(){    this.clearBoard();    // Ahhh, back in the context of the right 'this'!};

二:認為存在塊級作用域

JavaScript開發(fā)者中常見的混亂來源(也是常見的錯誤來源)是假設JavaScript為每個代碼塊創(chuàng)建一個新的作用域。盡管這在許多其他語言中是對的,但在JavaScript中卻不是。

考慮一下下面的代碼:

???????

for (var i = 0; i < 10; i++) {    /* ... */}console.log(i);??//?輸出什么?

如果你猜測console.log()的調用會輸出 undefined 或者拋出一個錯誤,那你就猜錯了。答案是輸出10。為什么呢?

在大多數(shù)其他語言中,上面的代碼會導致一個錯誤,因為變量i的 "生命"(即使作用域)會被限制在for塊中。但在JavaScript中,情況并非如此,即使在for循環(huán)完成后,變量i仍然在作用域內,在退出循環(huán)后仍保留其最后的值。(順便說一下,這種行為被稱為變量提升(variable hoisting)。

JavaScript中對塊級作用域的支持是通過let關鍵字實現(xiàn)的。Let關鍵字已經(jīng)被瀏覽器和Node.js等后端JavaScript引擎廣泛支持了多年。

三:創(chuàng)建內存泄漏

如果沒有有意識地編寫代碼來避免內存泄漏,那么內存泄漏幾乎是不可避免的JavaScript問題。它們的發(fā)生方式有很多種,所以我們只重點介紹幾種比較常見的情況。

內存泄漏實例:對不存在的對象的懸空引用

考慮以下代碼:

???????

var theThing = null;var replaceThing = function () {  var priorThing = theThing;   var unused = function () {     // 'unused'是'priorThing'被引用的唯一地方。    // 但'unused'從未被調用過    if (priorThing) {      console.log("hi");    }  };  theThing = {    longStr: new Array(1000000).join('*'),  // 創(chuàng)建一個1MB的對象    someMethod: function () {      console.log(someMessage);    }  };};setInterval(replaceThing, 1000);    // 每秒鐘調用一次 "replaceThing"。

如果你運行上述代碼并監(jiān)測內存使用情況,你會發(fā)現(xiàn)你有一個明顯的內存泄漏,每秒泄漏整整一兆字節(jié)!而即使是手動垃圾收集器(GC)也無濟于事。因此,看起來我們每次調用 replaceThing 都會泄漏 longStr。但是為什么呢?

每個theThing對象包含它自己的1MB longStr對象。每一秒鐘,當我們調用 replaceThing 時,它都會在 priorThing 中保持對先前 theThing 對象的引用。

但是我們仍然認為這不會是一個問題,因為每次通過,先前引用的priorThing將被取消引用(當priorThing通過priorThing = theThing;被重置時)。而且,只在 replaceThing 的主體和unused的函數(shù)中被引用,而事實上,從未被使用。

因此,我們又一次想知道為什么這里會有內存泄漏。

為了理解發(fā)生了什么,我們需要更好地理解JavaScript的內部工作。實現(xiàn)閉包的典型方式是,每個函數(shù)對象都有一個鏈接到代表其詞法作用域的字典式對象。如果在replaceThing里面定義的兩個函數(shù)實際上都使用了priorThing,那么它們都得到了相同的對象就很重要,即使priorThing被反復賦值,所以兩個函數(shù)都共享相同的詞法環(huán)境。但是一旦一個變量被任何閉包使用,它就會在該作用域內所有閉包共享的詞法環(huán)境中結束。而這個小小的細微差別正是導致這個可怕的內存泄露的原因。

避免內存泄漏:要點

JavaScript的內存管理(尤其是垃圾回收)主要是基于對象可達性的概念。

以下對象被認為是可達的,被稱為 "根":

●?從當前調用堆棧的任何地方引用的對象(即當前被調用的函數(shù)中的所有局部變量和參數(shù),以及閉包作用域內的所有變量)

●?所有全局變量

只要對象可以通過引用或引用鏈從任何一個根部訪問,它們就會被保留在內存中。

瀏覽器中有一個垃圾收集器,它可以清理被無法到達的對象所占用的內存;換句話說,當且僅當GC認為對象無法到達時,才會將其從內存中刪除。不幸的是,很容易出現(xiàn)不再使用的 "僵尸 "對象,但GC仍然認為它們是 "可達的"。

四:雙等號的困惑

JavaScript 的一個便利之處在于,它會自動將布爾上下文中引用的任何值強制為布爾值。但在有些情況下,這可能會讓人困惑,因為它很方便。例如,下面的一些情況對許多JavaScript開發(fā)者來說是很麻煩的。

???????

// 下面結果都是 'true'console.log(false == '0');console.log(null == undefined);console.log(" \t\r\n" == 0);console.log('' == 0);
// 下面也都成立if ({}) // ...if?([])?//?...

關于最后兩個,盡管是空的(大家可能會覺得他們是 false),{}和[]實際上都是對象,任何對象在JavaScript中都會被強制為布爾值 "true",這與ECMA-262規(guī)范一致。

正如這些例子所表明的,類型強制的規(guī)則有時非常清楚。因此,除非明確需要類型強制,否則最好使用===和!==(而不是==和!=),以避免強制類型轉換的帶來非預期的副作用。(== 和 != 會自動進行類型轉換,而 === 和 !== 則相反)

另外需要注意的是:將NaN與任何東西(甚至是NaN)進行比較時結果都是 false。因此,不能使用雙等運算符(==, ==, !=, !==)來確定一個值是否是NaN。如果需要,可以使用內置的全局 isNaN()函數(shù)。

???????

console.log(NaN == NaN);    // Falseconsole.log(NaN === NaN);   // Falseconsole.log(isNaN(NaN));????//?True

五:低效的DOM操作

使用 JavaScript 操作DOM(即添加、修改和刪除元素)是相對容易,但操作效率卻不怎么樣。

比如,每次添加一系列DOM元素。添加一個DOM元素是一個昂貴的操作。連續(xù)添加多個DOM元素的代碼是低效的。

當需要添加多個DOM元素時,一個有效的替代方法是使用 document fragments來代替,從而提高效率和性能。

???????

var div = document.getElementsByTagName("my_div");
var fragment = document.createDocumentFragment();
for (var e = 0; e < elems.length; e++) {  // elems previously set to list of elements    fragment.appendChild(elems[e]);}div.appendChild(fragment.cloneNode(true));

除了這種方法固有的效率提高外,創(chuàng)建附加的DOM元素是很昂貴的,而在分離的情況下創(chuàng)建和修改它們,然后再將它們附加上,就會產(chǎn)生更好的性能。

六:在循環(huán)內錯誤使用函數(shù)定義

考慮下面代碼:

???????

var elements = document.getElementsByTagName('input');var n = elements.length;    // Assume we have 10 elements for this examplefor (var i = 0; i < n; i++) {    elements[i].onclick = function() {        console.log("This is element #" + i);    };}

根據(jù)上面的代碼,如果有10個 input 元素,點擊任何一個都會顯示 "This is element #10"。這是因為,當任何一個元素的onclick被調用時,上面的for循環(huán)已經(jīng)結束,i的值已經(jīng)是10了(對于所有的元素)。

我們可以像下面這樣來解決這個問題:

???????

var elements = document.getElementsByTagName('input');var n = elements.length;   var makeHandler = function(num) {      return function() {           console.log("This is element #" + num);     };};for (var i = 0; i < n; i++) {    elements[i].onclick = makeHandler(i+1);}

makeHandler 是一個外部函數(shù),并返回一個內部函數(shù),這樣就會形成一個閉包,num 就會調用時傳進來的的當時值,這樣在點擊元素時,就能顯示正確的序號。

七:未能正確利用原型繼承

考慮下面代碼:

???????

BaseObject = function(name) {    if (typeof name !== "undefined") {        this.name = name;    } else {        this.name = 'default'    }};

上面代碼比較簡單,就是提供了一個名字,就使用它,否則返回 default:

???????

var firstObj = new BaseObject();var secondObj = new BaseObject('unique');
console.log(firstObj.name);  // -> 'default'console.log(secondObj.name);?//?->?'unique'

但是,如果這么做呢:

delete?secondObj.name;

會得到:

console.log(secondObj.name);?//?'undefined'

當使用 delete 刪除該屬性時,就會返回一個 undefined,那么如果我們也想返回 default 要怎么做呢?利用原型繼承,如下所示:???????

BaseObject = function (name) {    if(typeof name !== "undefined") {        this.name = name;    }};
BaseObject.prototype.name?=?'default';

BaseObject 從它的原型對象中繼承了name 屬性,值為 default。因此,如果構造函數(shù)在沒有 name 的情況下被調用,name 將默認為 default。同樣,如果 name 屬性從BaseObject的一個實例中被移除,那么會找到原型鏈的 name,,其值仍然是default。所以???????

var thirdObj = new BaseObject('unique');console.log(thirdObj.name);  // -> Results in 'unique'
delete thirdObj.name;console.log(thirdObj.name);??//?->?Results?in?'default'

八:為實例方法創(chuàng)建錯誤的引用

考慮下面代碼:???????

var MyObject = function() {}
MyObject.prototype.whoAmI = function() {    console.log(this === window ? "window" : "MyObj");};
var?obj?=?new?MyObject();

現(xiàn)在,為了操作方便,我們創(chuàng)建一個對whoAmI方法的引用,這樣通過whoAmI()而不是更長的obj.whoAmI()來調用。

var?whoAmI?=?obj.whoAmI;

為了確保沒有問題,我們把 whoAmI 打印出來看一下:

console.log(whoAmI);

為了確保沒有問題,我們把 whoAmI 打印出來看一下:

console.log(whoAmI);

輸出:

???????

function () {    console.log(this === window ? "window" : "MyObj");}

看起來沒啥問題。

接著,看看當我們調用obj.whoAmI() 和 whoAmI() 的區(qū)別。

???????

obj.whoAmI();  // Outputs "MyObj" (as expected)whoAmI();      // Outputs "window" (uh-oh!)

什么地方出錯了?當我們進行賦值時 var whoAmI = obj.whoAmI,新的變量whoAmI被定義在全局命名空間。結果,this的值是 window,而不是 MyObject 的 obj 實例!

因此,如果我們真的需要為一個對象的現(xiàn)有方法創(chuàng)建一個引用,我們需要確保在該對象的名字空間內進行,以保留 this值。一種方法是這樣做:

???????

var MyObject = function() {}
MyObject.prototype.whoAmI = function() {    console.log(this === window ? "window" : "MyObj");};
var obj = new MyObject();obj.w = obj.whoAmI;   // Still in the obj namespace
obj.whoAmI();  // Outputs "MyObj" (as expected)obj.w();???????//?Outputs?"MyObj"?(as?expected)

九:為 setTimeout 或 setInterval 提供一個字符串作為第一個參數(shù)

首先,需要知道的是為 setTimeout 或 setInterval 提供一個字符串作為第一個參數(shù),這本身并不是一個錯誤。它是完全合法的JavaScript代碼。這里的問題更多的是性能和效率的問題。很少有人解釋的是,如果你把字符串作為setTimeout或setInterval的第一個參數(shù),它將被傳遞給函數(shù)構造器,被轉換成一個新函數(shù)。這個過程可能很慢,效率也很低,而且很少有必要。

將一個字符串作為這些方法的第一個參數(shù)的替代方法是傳入一個函數(shù)???????

setInterval("logTime()", 1000);setTimeout("logMessage('"?+?msgValue?+?"')",?1000);

更好的選擇是傳入一個函數(shù)作為初始參數(shù):

??????????????

setInterval(logTime, 1000); 
setTimeout(function() {          logMessage(msgValue);     },?1000);

十:未使用 "嚴格模式"

"嚴格模式"(即在JavaScript源文件的開頭包括 "use strict";)是一種自愿在運行時對JavaScript代碼執(zhí)行更嚴格的解析和錯誤處理的方式,同時也使它更安全。

但是,不使用嚴格模式本身并不是一個 "錯誤",但它的使用越來越受到鼓勵,不使用也越來越被認為是不好的形式。

以下是嚴格模式的一些主要好處:

●?使得調試更容易。原本會被忽略或無感知的代碼錯誤,現(xiàn)在會產(chǎn)生錯誤或拋出異常,提醒我們更快地發(fā)現(xiàn)代碼庫中的JavaScript問題,并引導更快地找到其來源。

●?防止意外的全局變量。在沒有嚴格模式的情況下,給一個未聲明的變量賦值會自動創(chuàng)建一個具有該名稱的全局變量。這是最常見的JavaScript錯誤之一。在嚴格模式下,試圖這樣做會產(chǎn)生一個錯誤。

●?消除this 強迫性。在沒有嚴格模式的情況下,對 null 或 undefined 的 this 值的引用會自動被強制到全局。在嚴格模式下,引用null或undefined的this值會產(chǎn)生錯誤。

●?不允許重復的屬性名或參數(shù)值。嚴格模式在檢測到一個對象中的重復命名的屬性(例如,var object = {foo: "bar", foo: "baz"};)或一個函數(shù)的重復命名的參數(shù)(例如,function foo(val1, val2, val1){})時拋出一個錯誤,從而捕捉到你的代碼中幾乎肯定是一個錯誤,否則你可能會浪費很多時間去追蹤。

●?使得eval()更加安全。eval()在嚴格模式和非嚴格模式下的行為方式有一些不同。最重要的是,在嚴格模式下,在eval()語句中聲明的變量和函數(shù)不會在包含的范圍內創(chuàng)建。(在非嚴格模式下,它們是在包含域中創(chuàng)建的,這也可能是JavaScript問題的一個常見來源)。

●?在無效使用delete的情況下拋出錯誤。delete 操作符(用于從對象中刪除屬性)不能用于對象的非可配置屬性。當試圖刪除一個不可配置的屬性時,非嚴格的代碼將無聲地失敗,而嚴格模式在這種情況下將拋出一個錯誤。

代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行l(wèi)og 調試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具。

http://www.risenshineclean.com/news/6744.html

相關文章:

  • wordpress小程序調用數(shù)據(jù)庫字段長沙優(yōu)化網(wǎng)站推廣
  • 網(wǎng)站建設需要什么教材網(wǎng)絡營銷策略實施的步驟
  • 做網(wǎng)站備案需要什么百度推廣的廣告真實可信嗎
  • 自己做網(wǎng)站花多少錢域名是什么 有什么用
  • 河北省建設機械協(xié)會是真的網(wǎng)站嗎聊城seo
  • 營銷類網(wǎng)站建設百度刷排名優(yōu)化軟件
  • 網(wǎng)站開發(fā)軟件最流行蘇州搜索引擎優(yōu)化
  • 哪個網(wǎng)站是做包裝材料珍珠棉包管seo推廣一個月見效
  • 公司網(wǎng)站不續(xù)費能打開網(wǎng)頁嗎seo研究所
  • 對手網(wǎng)站分析如何修改百度上面的門店號碼
  • 后海做網(wǎng)站公司湖南百度推廣代理商
  • 福州外文網(wǎng)站建設seo網(wǎng)站優(yōu)化知識
  • 沈陽房地產(chǎn)網(wǎng)站開發(fā)西點培訓班一般要多少學費
  • 東莞市建設局網(wǎng)站首頁營銷策略怎么寫
  • 做京東網(wǎng)站需要哪些手續(xù)重慶網(wǎng)站建設公司
  • 二維碼轉短鏈接生成器做排名優(yōu)化
  • 河南專業(yè)網(wǎng)站建設公司哪家好學好seo
  • oracle 網(wǎng)站開發(fā)推廣引流app
  • 網(wǎng)站建設原理與實踐推廣普通話手抄報文字內容
  • 建動畫網(wǎng)站需要多少錢關鍵詞排名查詢工具免費
  • 域名服務商怎么查詢網(wǎng)絡優(yōu)化推廣公司哪家好
  • 贛州人才網(wǎng)官方網(wǎng)站合肥網(wǎng)站優(yōu)化平臺
  • 網(wǎng)站開發(fā)有哪些參考文獻域名權重查詢
  • wordpress電影主題會員廈門seo蜘蛛屯
  • 工裝設計方案網(wǎng)站seosem是什么職位
  • 國內論壇網(wǎng)站有哪些免費網(wǎng)站排名優(yōu)化在線
  • 怎么做商城網(wǎng)站全國最好的廣告公司加盟
  • 網(wǎng)站建設公司行業(yè)9 1短視頻安裝
  • 網(wǎng)站ui是平面設計嗎信息流推廣渠道
  • cms網(wǎng)站系統(tǒng)天津seo培訓