日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JS的数据访问及优化访问速度

發布時間:2025/5/22 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JS的数据访问及优化访问速度 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JavaScript中有四種基本的數據存取位置:

  • ? 直接量

直接量只代表自身,不存儲在特定位置。JS中的直接量有:字符串,數字,布爾值,對象,數組,函數,正則表達式,以及特殊的null和undefined值。

  • ? 變量

用var定義的數據存儲單元

  • 數組元素

存儲在JS數組對象內部,以數字作為索引

  • ? 數據成員

存儲在JS對象內部,以字符串為索引

作用域工作原理和標識符解析

關鍵字:內部屬性[[Scope]]、可變對象、運行期上下文、執行環境、活動對象

1. 作用域工作原理

?

作用域鏈的作用:存儲執行環境可以訪問的數據,使用方法是標識符解析

每一個JS函數都表示為一個對象,更確切的說,是Function對象的一個實例。Function對象同其他對象一樣,擁有可以編程訪問的屬性,和一系列不能通過代碼訪問而僅供JS引擎存取的內部屬性。內部屬性[[Scope]]指向一個函數被創建的作用域中對象的集合。這個集合被稱為函數的作用域鏈,它決定哪些數據可以被函數訪問。函數作用域中的每個對象被稱為可變對象,每個可變對象都以“鍵值對”的形式存在。當一個函數被創建后,它的作用域鏈會被創建此函數的作用域中可訪問的數據對象所填充。思考下面的全局函數

function add(num1, num2) {????????????

???????? var sum = num1 + num2;

???????? return sum;

}

當函數add()創建時,它的作用域鏈填入了一個單獨的可變對象,包含了函數能訪問到的所有數據。本可變對象是時刻存在的全局對象。

函數add的作用域將會在執行時用到。

var total = add(1, 2);

???????? 執行此函數時會創建一個稱為”運行期上下文”的內部對象。一個運行期上下文定義了一個函數的執行環境。函數每次執行時對應的運行期上下文都是獨一無二的,所以多次調用同一函數就會導致創建多個運行期上下文。當函數執行完畢,執行期上下文會被銷毀。

???????? 每個運行期上下文都有自己的作用域鏈,用于標識符解析。當它被創建時,它的作用域鏈被初始化為當前運行函數的[[Scope]]屬性所指向的對象。這些值按照它們出現在函數中的順序,被復制到運行期上下文的作用域鏈中。這個過程一旦完成,一個被稱為”活動對象”的新對象就為運行期上下文創建好了?;顒訉ο笞鳛楹瘮颠\行期中的可變對象,包含了所有局部變量、命名參數、參數集合arguments以及this.然后此對象被推入到作用域鏈的前端。當運行期上下文被銷毀,活動對象也隨之銷毀。

2. 標識符解析過程

???????? 在函數執行過程中,每遇到一個變量,都會經歷一次標識符解析過程以決定從哪里獲取或存儲數據。該過程搜索運行期上下文的作用域鏈,查找同名的標識符。搜索過程從作用域鏈頭部開始,也就是當前運行函數的活動對象。如果找到了,就使用這個標識符對應的變量;如果沒找到,繼續搜索作用域鏈中的下一個對象。搜索過程會持續進行,直到標識符被找到,或者沒有可用于搜索的對象為止,這種情況下標識符被認為是未定義的。函數執行過程中,每個標識符都要經歷這樣的搜索過程。

???????? 對于所有瀏覽器而言,總的趨勢是,一個標識符所在的位置越深(作用域鏈末端),它的讀寫速度也就越慢。一個好的經驗法則是:如果某個跨作用域值在函數中被引用一次以上,那么就把它存儲在局部變量里。

閉包,作用域和內存

官方解釋為: 所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。
我認為閉包就是能夠讀/寫函數內部的某些變量的子函數,并將這些變量保存在內存中.

function assignEvents() {

???????? var id = ‘index’;

???????? document.getElementById(“save-btn”).onclick = function(event) {

???????? saveDocument(id);

? ? };

}

函數給一個DOM元素設置事件處理器。這個事件處理器就是一個閉包,它在函數執行時被創建,并且能訪問所屬作用域的id變量。為了讓這個閉包訪問id變量,必須創建一個特別的作用域鏈。

???????? 當assignEvents()函數被執行時,一個包含變量id的以及其他一些數據的活動對象被創建。它成為運行期上下文作用域鏈中第一個對象,而全局對象緊隨其后。當閉包被創建時,它的[[Scope]]屬性被初始化為這些對象。(如圖)

因為閉包的[[Scope]]屬性包含了與運行期上下文作用域相同的對象的引用,因此會有一些副作用。

通常的活動對象會隨同運行期上下文一同銷毀。但引入閉包時,由于引用仍然存在閉包的[[Scope]]屬性中,因此活動對象無法被銷毀。這意味著閉包的存在,需要更多的內存開銷。

???????? 當閉包被執行時,一個運行期上下文被創建,它的作用域鏈與屬性[[Scope]]中引用的兩個相同的作用域鏈對象同時被初始化,然后一個活動對象為閉包自身所創建。

???????? 注意在閉包中用到的兩個標識符,id和saveDocument,它們存在作用域鏈第一個對象之后的位置。這就是使用閉包最主要的性能關注點:要經常訪問大量跨作用域的標識符,每次訪問都會導致性能損失。

閉包的應用環境

1. 保護函數內的變量安全

2. 在內存中維持一個變量

????????

對象成員

???????? 訪問對象成員的速度比訪問直接量或變量更慢,在某些瀏覽器中比訪問數組元素還要慢。

???????? JS中的對象是基于原型的。原型是其他對象的基礎,定義并實現了一個新對象必須包含的成員列表。這一概念完全不同于傳統面向對象編程語言的‘類’的概念,‘類’定義了創建新對象的過程。而原型對象為所有對象實例所共享,因此這些實例也共享了原型對象的成員。

???????? 實例通過一個內部屬性綁定它的原型__proto__,比如一旦你創建一個內置對象(Object、Array)的實例,它們就會自動擁有一個Object實例作為原型。

???????? 實例可以有兩種成員類型:

實例成員(也稱‘own’成員):存在對象實例中

原型成員:由對象原型繼承而來。

var Book = {

???????? title: “JavaScript”,

???????? content: ‘JavaScript是一門博大精深的語言’

};

alert(BooK.toString());????????????? //[object Object]

???????? 方法toString()是對象Book繼承而來的原型成員。解析對象成員的過程同解析變量十分相似。當Book.toString()

被調用時,會從對象實例開始,搜索名為’toString’成員。如果實例中不存在,那么會繼續搜索其原型對象,直到

toString()方法被找到并且執行。實例可以訪問它原型中的每一個屬性和方法。

hasOwnProperty()判斷對象是否包含特定的實例成員。

in操作符判斷對象是否包含特定的屬性。

原型鏈

???????? 對象的原型決定了實例的類型。默認情況下,所有對象都是Object的實例,并繼承了所有基本方法。

嵌套成員

???????? window.localhost.href每次遇到點操作符,嵌套成員會導致JavaScript引擎搜索所有對象成員。這些屬性不是對象的實例屬性,那么成員解析還需要搜索原型鏈,這會花更多的時間。

???????? 緩存對象成員值,不適合緩存對象的方法。

小結:

  • 訪問直接量和局部變量速度最快,相反,訪問數據元素和對象成員相對較慢。
  • 由于局部變量存在于作用域的起始位置,因此訪問它比訪問跨作用域變量更快。變量在作用域鏈中的位置越深,訪問時間就越長。全局變量的訪問所需時間最長,因為它處于作用域鏈的最末端。
  • 嵌套的對象成員會明顯影響性能,盡量少用。
  • 屬性或方法在原型鏈中的位置越深,訪問它的速度也越慢(和訪問變量相似)。
  • 通常來說,可以通過把常用的對象成員、數組元素、跨域變量保存在局部變量中來改善JS性能,因為局部變量訪問速度更快。
  • 摘自:高性能JavaScript

    轉載于:https://www.cnblogs.com/mackxu/archive/2012/12/02/2798744.html

    總結

    以上是生活随笔為你收集整理的JS的数据访问及优化访问速度的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。