❶ vue使用require.context,動態變數怎麼辦
在日常的功能練習和調試過程中,需要一個demo項目進行功能測試,由於頻繁.vue頁面的同時,又要再router.js文件裡面注冊路由,感覺有點無聊和枯燥。基於此出發點,考慮能否自動讀取文件夾下的文件進行路由注冊。
借鑒拍纖思路:
參考vue的功能基礎組件的自動化全局注冊,看到一個require.context方法,可以讀取某個文件夾下的文件信息。因此考慮,使用這個方法,獲取views文件夾下的.vue頁面,文件夾名稱作為路由名稱
require.context的使用介紹:
一個webpack的api,通過執行require.context函數獲取一個特定的上下文,主要用來實現自動化導入模塊,在前端工程中,如果遇到從一個文件夾引入很多模塊的情況,可以使用這個api,它會遍歷文件夾中的指定文件,然後自動導入,使得不需要每次顯式的調用import導入模塊
頁面代碼:
如下圖示,views文件夾下的內容,都需要進行路由注冊。
文件的路徑有2種,(1)簡單的vue功能頁面,直接掛在views文件夾下;(2)復雜的頁面,在views下在新建文件夾進行處理。
目前需要自動注冊的路由頁面,是針對「直接掛在views文件夾」下的頁面。(因為views下的二級頁面,暫時沒有想到好的方案)
router/index.js頁面代碼
心路歷程:
(1)一開襲渣仿始的想法,是想著用數組對象的方式定義好,路由名稱和引入的路徑地址,但是覺得還是不夠自動化,新建.vue文件的時候還是需要手動添加;
(2)後來想到用使用require.context方法得到fileName,然後根據字元串裁減和拼接,得到我所需的url和文件相對路徑;
例如: component: () =>import(【變數】),但是後來發現,import()裡面,不能使用變數!!!!!!!!!
原因:根據es6mole語法,由於import是靜態執行,所以不能使用表達式和變數這些只有在運行時才能得到結果的語法結構。
(3)由由於import的使用限制,不能動態使用() =>import的語法,因此在考慮,能否直接替換掉這種異梁沖步載入引入的寫法。經過分析,得出pathConfig欄位裡面有一個屬性的內容,是指定的vue頁面的default模塊內容。經測試,可以使用。
pathConfig的列印內容如下示:
(4)因此「views」文件夾下的".vue"文件,引入成功,並用變數routerAry存儲起來,使用concat方法把其他需要手動注冊的路由信息,連接起來,進行路由注冊。
❷ iOS - OC 與 JS 交互六種方式總結
在 APP 中,免不了與 H5頁面打交道,所以掌握 與 JS 交互就顯的至關重要,本文總結了常見的與 JS 交互方式。
注意事項
在 OC 原生中
在 html 文件中
早期的JS與原生交互的開源庫很多都是用得這種方式來實現的,例如:PhoneGap、 WebViewjavascriptBridge 。
效果圖
使用WKNavigationDelegate中的代理方法,攔截自定義的 URL 來實現 JS 調用 OC 方法。
注意點
關於如何區分執行不同的OC 方法,也與UIWebView的處理方式一樣,通過URL 的host 來區分執行不同的方法:
JS 調用OC 方法後,有的操作可能需要將結果返回給JS。這時候就是OC 調用JS 方法的場景。
WKWebView 提供了一個新的方法 evaluateJavaScript:completionHandler: ,實現OC 調用JS 等場景。
注意點
運行結果
在iOS 7之後,apple添加了一個新的庫JavaScriptCore,用來做JS交互,因此JS與原生OC交互也變得簡單了許多。
首先導入JavaScriptCore庫, 然後在OC中獲取JS的上下文。
再然後定義好JS需要調用的方法,例如JS要調用share方法:
則可以在UIWebView載入url完成後,在其代理方法中添加要調用的share方法:
OC 調用 JS 方法有多種,首先介紹使用JavaScriptCore框架的方式。
使用JSContext 的方法 -evaluateScript ,可以實現 OC 調用 JS 方法
效果圖
使用WKWebView的時候,如果想要實現JS調用OC方法,除了攔截URL之外,還有一種簡單的方式。那就是利用WKWebView的新特性MessageHandler來實現JS調用原生方法。
創建 WKWebViewConfiguration 對象,配置各個API對應的MessageHandler。
然後在界面即將顯示的時候添加MessageHandler
需要注意的是addScriptMessageHandler很容易引起循環引用,導致控制器無法被釋放,所以需要移除MessageHandler
這里實現了兩個協議 <WKUIDelegate,WKScriptMessageHandler> , WKUIDelegate 是因為我在JS中彈出了alert 。 WKScriptMessageHandler 是因為我們要處理JS調用OC方法的請求。
WKScriptMessage 有兩個關鍵屬性 name 和 body 。
因為我們給每一個OC 方法取了一個name,那麼我們就可以根據name 來區分執行不同的方法。body 中存著JS 要給OC 傳的參數。
關於參數body 的解析,我就舉一個body中放字典的例子,其他的稍後可以看demo。
解析JS 調用OC 實現分享的參數:
message.boby 就是JS 里傳過來的參數。我們不同的方法先做一下容錯性判斷。然後正常取值就可以了。
下面只列舉一個shareClick()方法,其他看Demo
這里使用WKWebView 實現OC 調用JS方法與之前說的文章一樣,通過
- evaluateJavaScript:completionHandler:
效果圖如下圖所示
詳情看下面文章鏈接
iOS下 JS 與 OC 互相調用(五) - UIWebView+WebViewJavascriptBridge
詳情看下面文章鏈接
iOS下 JS 與 OC 互相調用(六) - WKWebView+WKWebViewJavascriptBridge
iOS下 JS 與OC 互相調用(一) - UIWebView 攔截 URL
iOS下 JS 與OC 互相調用(二) - JavaScriptCore
iOS 下 JS 與 OC 互相調用(三) - WKWebView 攔截 URL
iOS下JS與OC互相調用(四)-MessageHandler
iOS下 JS 與 OC 互相調用(五) - UIWebView+WebViewJavascriptBridge
iOS下 JS 與 OC 互相調用(六) - WKWebView+WKWebViewJavascriptBridge
❸ 什麼是JS
您好,非常榮幸能在此回答您的問題。以下是我對此問題的部分見解,若有錯誤,歡迎指出。展開全部
JavaScript是個腳本編程語言,支持Web應用程序的客戶端和伺服器端構件的開發.在客戶端,它用於編寫Web瀏覽器在Web頁面上下文中執行的程序,在伺服器端,它可用於編寫用於處理Web瀏覽器提交的信息並相應地更新瀏覽器顯示的頁面。在前面介紹HTML時,我們曾經講到如果想要實現更多的互動網頁,就要在客戶端和伺服器端對數據進行處理,而對於客戶端的處理主要是配合客戶端網頁技術的Script語言,它在設計網頁時扮演的角色
◆動態網頁:JavaScript能夠開發與用戶雙向互動的功能,因為不需要將數據在客戶端和伺服器間來回傳遞,在速度上擁有即時的反應效果,因為程序直接在瀏覽器執行。
◆表單處理與驗證:作為表單欄位的驗證,檢查表單欄位是否輸入錯誤。
◆瀏覽器對象:直接使用瀏覽器對象,建立復雜的網頁內容,例如:打開新窗口載入網頁。當然利用JavaScript我們還可以製作出各種個樣的圖片,文字,滑鼠,動畫和頁面的效果,甚至還 可以做各種客戶端的小游戲呢!JavaScript可以插入到HTML文件內進行製作。若想使用JavaScript,應通過下面的格式將其插入HTML文件。 JavaScript代碼
◆LANGUAGE:設定Script語言的種類。若為JavaScript,則填寫JavaScript;若為VBScript,則填寫VBScript。
◆SRT:設定包含路徑的文件名,例如"C:/JScript/test.js"。Script標記可以放在HTML文檔的head或body中,多數情況下,最好把Script標記放在文檔頭部,以確保腳本中的所有JavsScript定義均在文檔主體之前。
◆JavaScript的說明語句使用了類似C++和JAVA的語法,"//"表示說明直到行尾,"/*"和"/*"表示其中的內容為說明信息。通過JavaScript不僅可以向Document對象寫入簡單文本,也可以用JavaScript生成在當前文檔中顯示的HTML元素。JavaScript和其它編程語言一樣,用變數存放數值.變數可以在程序其他部分使用。變數名可以用大寫字母(A-Z),小寫字母(a-z),和下劃線開頭,其餘的字元可以使用字母,下劃線或數字,變數名是區分大小寫的。與其他語言不同的是,JavaScript並不要求指定變數中包含的數據類型(甚至無法指定)。事實上,JavaScript能夠自動識別所輸入的數字或符號,所以在JavaScript中,不需設定數據類型。但另一方面,由於JavaScript自動完成不同類型之間的轉換,所以一定要跟蹤變數的數值類型,及其變數表達式中的轉換過程。
JavaScript支持以下四種基本數值類型。整數:表示整數的方法有10進制,8進制和16進制。就一般使用的數值而言,16進制是指0-15的數值,在JavaScript中,在其前面加"0x",標志其為16進制,8進制是在0-7前面加"0"。 浮點數:表示小數,很大的數或極小數,也可以是要用指數計數表示的數。表示較大數值時,可用E表示指數。 字元串:字元串被雙引號("")或單引號(')標識後加以使用。雙引號中或單引號中的數字不作為數字而作為字元串使用。因此這些數字不能參加計算。NaN:NaN即'Not a Number'表示是非數字的含義。在JavaScript內使用內置函數或錯誤字元串時,將會返回NaN這一特殊值。 Null:Null是指JavaScript內使用了空值。沒有聲明的變數,或者沒有賦予任和值的變數就會返回Null值。它與數值0和空字元串("")有所區別。
除了前面介紹的基本類型外,JavaScript還支持兩個復雜類型的變數,數組和對象,它們是用基本字元串,數字和邏輯類型構造起來的。 數組:數組是能夠存放一序列數值的對象,這些數值存放在數組的索引位置中。例如:可以用數組存放公司員工的資料,要在Web頁面上顯示員工姓名,可以用數組名跟蹤員工姓名。非常感謝您的耐心觀看,如有幫助請採納,祝生活愉快!謝謝!
❹ Web前端學習之Javascript繼承的常用4種方法
今天小編要跟大家分享的文章是關於Javascript繼承的常用4種方法。相信很多學習web前端開發技術的小夥伴在學習前端開發的javascript部分的時候,在面向對象的部分就很難走下去了,主要的原因還是邏輯更加復雜了,需要理解的內容比直觀的開發布局難一點。
在面向對象編程里,封裝和繼承是比較重要的,這中間,薯鏈手繼承是相對而言比較難理解的,因為javascript的繼承方式比較多,也有不同的優缺點。今天小編為大家帶來這篇文章就是來和大家一起說一說Javascript繼承的常用4種方法,希望能夠對你有所幫助。
1、原型鏈繼承
核心:將父類的實例作為子類的原型
缺點:父類新增原型方法/原型屬性,子類都能訪問到,父類一變其它的都變了
2、構造繼承
基本思想
借用構造函數的基本思想就是利用call或者apply把父類中通過this指定的屬性和方法復制(借用)到子類創建的實例中。
因為this對象是在運行時基於函數的執行環境綁定的。也就是說,在全局中,this等於window,而當函數被作為某個對象的方法調用時,this等於那個對象。
call、apply方法可將一個函數的對象上下文從初始的上下文改變為由thisObj指定的新對象。
所以,這個借用構造函數就是,new對象的時候(new創建的時候,this指喚昌向創建的這個實例),創建了一個新的實例對象,並且執行Parent裡面的代碼,而Parent裡面用call調用了Person,也就是說把this指向改成了指向新的實例,所以就會把Person裡面的this相關屬性和方法賦值到新的實例上,而不是賦值到Person上面,所以所有實例中就擁有了父類定義的這些this的屬性和方法。
因為屬性是綁定到this上面的,所以調用的時候才賦到相應的實例中,各個實例的值就不會互相影響了。
核心:使用父類的構造函數來增強子類實例,等於是復制父類的實例屬性給子類(沒用到原型)
缺點:方法都在構造函數中定義,
只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法,無法實現函數復用,每個子類都有父類實例函數的數嫌副本,影響性能
3、組合繼承
組合繼承(所有的實例都能擁有自己的屬性,並且可以使用相同的方法,組合繼承避免了原型鏈和借用構造函數的缺陷,結合了兩個的優點,是最常用的繼承方式)
核心:通過調用父類構造,繼承父類的屬性並保留傳參的優點,然後再通過將父類實例作為子類原型,實現函數復用
缺點:調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
4、寄生組合繼承
核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
缺點:堪稱完美,但實現較為復雜
以上就是小編今天為大家分享的關於web前端學習之Javascript繼承的常用4種方法的文章,希望本篇文章能夠對正在學習web前端技術的小夥伴們有所幫助。想要了解更多web前端知識記得關注北大青鳥web培訓官網。
文章轉載自公眾號:前端研究所
❺ js上下文傳遞
functionFUNC(){}
FUNC.prototype={
show:function(obj){
鬧緩液或模//==============在這里如何獲得invoker對象的引用?============
//obj為當前invoker對象的引用
}
};
varf=newFUNC();
functionINVOKER(){}
INVOKER.prototype={
invoke:團纖function(){
f.show(this);
}
};
varinvoker=newINVOKER();
invoker.invoke();
❻ webView換成WKWebView後,js注入self.jsContext應該怎麼處理才行
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
// 設置javaScriptContext上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"ios"] = self; self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue; NSLog(@"異常內信容息:%@", exceptionValue);
};
}
❼ 通過javascript執行鏈獲取上下文對象
一、介紹
本篇繼上一篇深入理解js執行--單線程的JS,這次我們來深入了解js執行過程中的執行上下文。
本篇涉及到的名詞:預執行,執行上下文,變數對象,活動對象,作用域鏈,this等
二、預執行
在上一篇說到,在js代碼被執行,執行上下文會被壓進執行棧中,但是在此之前還有一步工作要做,就是創建好執行上下文,因為創建好才能被壓進去啊。
創建執行上下文就是預執行過程:接下來說說創建執行上下文的細節部分。
三、創建執行上下文
(1)執行上下文組成
執行上下文:也叫一個執行環境,有全局執行環境和函數執行環境兩種。每個執行環境中包含這三部分:變數對象/活動對象,作用域鏈,this的值
代碼模擬
//可以把執行上下文看作一個對象exeContext = {
VO = [...], //VO代表變數對象,保存變數和函數聲明
scopeChain = [...]; //作用域鏈
thisValue = {...}; //this的值}
創建執行上下文就是創建變數對象,作用域鏈和this過程
接下來就分別細說創建變數對象/活動對象,作用域鏈,this值的過程。
(2)變數對象(variable object)
變數對象中存儲了在上下文(環境)中定義的變數和函數聲明
創建變數對象(VO)時就是將各種變數和函數聲明進行提升的環節:
//用下面代碼為例子console.log(a);console.log(b);console.log(c);console.log(d);var a = 100;
b = 10;function c(){};var d = function(){};
上述代碼的變數對象:
//這里用VO表示變數對象VO = {
a = undefined; //有a,a使用var聲明,值會被賦值為undefined
//沒有b,因為b沒用var聲明
c = function c (){} //有c,c是函數聲明,並且c指向該函數
d = undefined; //有d,d用var聲明,值會被賦值為undefined}
解說:執行上述代碼的時候,會創建一個全局執行上下文,上下文中包含上面變數對象,創建完執行上下文後,這個執行上下文才會被壓進執行棧中。開始執行後,因為js代碼一步一步被執行,後面賦值的代碼還沒被執行到,所以使用console.log函數列印各個變數的值是變數對象中的值。
在運行到第二行時會報錯(報錯後就不再執行了),因為沒有b(b is no defined)。把第二行注釋掉後,再執行各個結果就是VO裡面的對應的值。
講到這里我想大家對變數對象理解了吧,以及對變數提升和函數提升有個深入了解。
(3)活動對象(activation object)
活動對象是在函數執行上下文裡面的,其實也是變數對象,只是它需要在函數被調用時才被激活,而且初始化arguments,激活後就是看做變數對象執行上面一樣的步驟。
//例子function fn(name){ var age = 3; console.log(name);
}
fn('ry');
當上面的函數fn被調用,就會創建一個執行上下文,同時活動對象被激活
//活動對象AO = { arguments : {0:'ry'}, //arguments的值初始化為傳入的參數
name : ry, //形參初始化為傳進來的值
age : undefined //var 聲明的age,賦值為undefined}
活動對象其實也是變數對象,做著同樣的工作。其實不管變數還是活動對象,這里都表明了,全局執行和函數執行時都有一個變數對象來儲存著該上下文(環境內)定義的變數和函數。
(4)作用域鏈(scope chain)
在創建執行上下文時還要創建一個重要的東西,就是作用域鏈。每個執行環境的作用域鏈由當前環境的變數對象及父級環境的作用域鏈構成。
創建作用域鏈過程:
//以本段代碼為例function fn(a,b){ var x = 'string',
}
fn(1,2);
1.函數被調用前,初始化function fn,fn有個私有屬性[[scope]],它會被初始化為當前全局的作用域,fn.[[scope]="globalScope"。
2.調用函數fn(1,2),開始創建fn執行上下文,同時創建作用域鏈fn.scopeChain = [fn.[[scope]]],此時作用域鏈中有全局作用域。
3.fn活動對象AO被初始化後,把活動對象作為變數對象推到作用域鏈前端,此時fn.scopeChain = [fn.AO,fn.[[scope]]],構建完成,此時作用域鏈中有兩個值,一個當前活動對象,一個全局作用域。
fn的作用域鏈構建完成,作用域鏈中有兩個值,第一個是fn函數自身的活動對象,能訪問自身的變數,還有一個是全局作用域,所以fn能訪問外部的變數。這里就說明了為什麼函數中能夠訪問函數外部的變數,因為有作用域鏈,在自身找不到就順著作用域鏈往上找。
(5)this的值
上面說過執行上下文有兩種,一個全局執行上下文,一個函數執行上下,下面分別說說這兩種上下文的this。
a.全局執行上下文的this
指向window全局對象
b.函數執行上下文的this(主要講函數的this)
在《JavaScript權威指南》中有這么幾句話:
1.this是關鍵字,不是變數,不是屬性名,js語法不允許給this賦值。
2.關鍵字this沒有作用域限制,嵌套的函數不會從調用它的函數中繼承this。
3.如果嵌套函數作為方法調用,其this指向調用它的對象。
4.如果嵌套函數作為函數調用,其this值是window(非嚴格模式),或undefined(嚴格模式下)。
解讀一下:上面說的概括了this兩種值的情況:
1.函數直接作為某對象的方法被調用則函數的this指向該對象。
2.函數作為函數直接獨立調用(不是某對象的方法),或是函數中的函數,其this指向window。
我們看幾個栗子便可理解:
栗子1:(這個例子我相信都能理解)當函數被獨立運行時,其this的值指向window對象。
function a(){ console.log(this);
}//獨立運行a(); //window
栗子2:(函數中函數,這里嵌套了個外圍函數)這里也是指向window對象,也相當於函數作為函數調用,就是獨立運行。其實這個例子也說明閉包的this指向Window。
//外圍函數function a(){ //b函數在裡面
function b(){ console.log(this);
} //雖然在函數中,但b函數獨立運行,不是那個對象的方法
b();
}
a(); //window
栗子3:(再寫復雜點的話)x函數即使在對象裡面,但它是函數中的函數,也是作為函數運行,不是Object的方法。getName才是objcet的方法,所以getName的this指向object(在下個栗子有)。
//一個對象var object = { //getName是Object的方法
getName : function(){ //x是getName裡面的函數,它是作為函數調用的,this就是window啦
function x(){ console.log(this);
}
x();
}
}
object.getName(); //window
以上三個都是輸出window,下面是this指向某個對象的情況。
栗子4:函數作為某個對象的方法被調用。
//一個對象var object = {
name : "object", //getName是Object的方法
getName : function(){
console.log(this === object);
}
}object.getName(); //true , 說明this指向了object
這里的getName中的this是指向objct對象的,因為getName是object的一個方法,它作為對象方法被調用。
栗子5:再來個栗子。
var name = "window";var obj = {
name : "obj"};function fn (){ console.log(this.name);
}//將fn通過call或bind或apply直接綁定給obj,從而成為obj的方法。fn.call(obj); //obj
再總結一下this的值
全局執行上下文:this的值是window
函數執行上下文:this的值兩種:
1.函數中this指向某對象,因為函數作為對象的方法:怎麼看函數是對象的方法,一種是直接寫在對象裡面(不是嵌套在對象方法中的函數,不懂再看看栗子3),另一種是通過call等方法直接綁定在對象中。
2.函數中this指向window:函數獨立運行,不是對象的方法,函數中的函數(閉包),其this指向window。
四、總結整個js代碼執行過程
(1)JS執行過程
js代碼執行分成了兩部分:預執行和執行
預執行:創建好執行上下文,有兩種,一種是開始執行js代碼就創建全局的執行上下文,一種是當某個函數被調用時創建它自己的函數執行上下文。這里也就是本節主要講的東西,創建執行上下文的三個重要成分。
執行:在執行棧中執行,棧頂的執行上下文獲得執行權,並按順序執行當前上下文中的代碼,執行完後彈棧銷毀上下文,執行權交給下一個棧頂執行上下文。
(2)放上圖示
某個執行上下文生命周期:
五、後話
整個js的執行過程就這樣了,一開始可能有點難理解,但看多幾遍就慢慢領會了。希望大家能夠理解。如果覺得寫得好,記得點贊,關注哦。
❽ 如何查找網頁元素對應的JS代碼(如圖)
如果會調試,可以用打開瀏覽器的調試功能。
以chrome為例,按F12打開調試窗口內,切換到Sources選項卡,最右邊的容Event Listener Breakpoints里勾選Mouse下的mouseover即可,當滑鼠移動到圖片上時觸發mouseover事件,chrome可響應事件設置斷點,跟蹤js代碼查看就可以。
❾ Web前端工程師應該知道的JavaScript的10個難點!
今天小編要跟大家分享的文章是關於Web前端工程師應該知道的JavaScript的10個難點。相信很多正在學習Web前端知識的小夥伴對於JavaScript存在很多疑問,宏鄭敬為了幫助大家更好的學習Web前端知識,成為一名優秀的web前端工程師,今天小編為大家分享了這篇Web前端應該知道的JavaScript難點的問題,下面我們一起看一看吧!
1、立即執行函數
立即執行函數,即
(IIFE),正如它的名字,就是創建函數的同時立即執行。它沒有綁定任何事件,也無需等待任何非同步操作:
1.(function(){
2.
3.//代碼
4.
5.//...
6.
7.})();
function(){}是一個匿名函數,包圍它的一對括弧將其轉換為一個表達式,緊跟其後的一對括弧調用了這個函數。立即執行函數也可以理解為立即調用一個匿名函數。立即執行函數最常見的應用場景就是:將var變數的作用域限制於你們函數內,這樣可以避免命名沖突。
2、閉包
對於閉包(closure),當外部函數返回之後,內部函數依然可以訪問外部函數的變數。
1.(function(){
2.
3.//代碼
4.
5.//...
6.
7.})();
代碼中,外部函數f1隻執行了一次,變數N設為0,並將內部函數f2賦值給了變數result。由於外部函數f1已經執行完畢,其內部變數N應該在內存中被清除,然而事實並不是這樣:我們每次調用result的時候,發現變數N一直在內存中,並且在累加。為什麼呢?這就是閉包的神奇之處了!
3、使用閉包定義私有變數
通常,JavaScript開發者使用下劃線作為私有變數的前綴。但是實際上,這些變數依然可以被訪問和修改,並非真正的私有變數。這時,使用閉包可以定義真正的私有變數:1.functionProct(){
2.
3.varname;
4.
5.this.setName=function(value){
6.name=value;
7.};
8.
9.this.getName=function(){
10.returnname;
11.};
12.}
13.
14.varp=newProct();
15.p.setName("Fundebug");
16.
17.console.log(p.name);//輸出undefined
18.console.log(p.getName());//輸出Fundebug
代碼中,對象p的的name屬性為私有屬性,使用p.name不能直接訪問。
4、prototype
每個JavaScript構造函數都有一個prototype屬性,用於設置所有實例對象需要共享的屬蔽慎性和方法。prototype屬性不能列舉。JavaScript僅支持通過prototype屬性進行繼承屬性和方法。1.functionRectangle(x,y)
2.{
3.this._length=x;
4.this._breadth=y;
5.}
6.
7.Rectangle.prototype.getDimensions=function()
8.{
9.return{
10.length:this._length,
11.breadth:this._breadth
12.};
13.};
14.
15.varx=newRectangle(3,4);
16.vary=newRectangle(4,3);
17.
18.console.log(x.getDimensions());//{length:3,breadth:4}
19.console.log(y.getDimensions());//{length:4,breadth:3}
代碼中,x和y都是構造函數Rectangle創建的對象實例,叢返它們通過prototype繼承了getDimensions方法。
5、模塊化
JavaScript並非模塊化編程語言,至少ES6落地之前都不是。然而對於一個復雜的Web應用,模塊化編程是一個最基本的要求。這時,可以使用立即執行函數來實現模塊化,正如很多JS庫比如jQuery以及我們Fundebug都是這樣實現的。1.varmole=(function(){
2.varN=5;
3.
4.functionprint(x){
5.console.log("Theresultis:"+x);
6.}
7.
8.functionadd(a){
9.varx=a+N;
10.print(x);
11.}
12.
13.return{
14.description:"Thisisdescription",
15.add:add
16.};
17.})();
18.
19.
20.console.log(mole.description);//輸出"thisisdescription"
21.
22.mole.add(5);//輸出「Theresultis:10」
所謂模塊化,就是根據需要控制模塊內屬性與方法的可訪問性,即私有或者公開。在代碼中,mole為一個獨立的模塊,N為其私有屬性,print為其私有方法,decription為其公有屬性,add為其共有方法。
6、變數提升
JavaScript會將所有變數和函數聲明移動到它的作用域的最前面,這就是所謂的變數提升(Hoisting)。也就是說,無論你在什麼地方聲明變數和函數,解釋器都會將它們移動到作用域的最前面。因此我們可以先使用變數和函數,而後聲明它們。但是,僅僅是變數聲明被提升了,而變數賦值不會被提升。如果你不明白這一點,有時則會出錯:1.console.log(y);//輸出undefined
2.
3.y=2;//初始化y
上面的代碼等價於下面的代碼:1.vary;//聲明y
2.
3.console.log(y);//輸出undefined
4.
5.y=2;//初始化y
為了避免BUG,開發者應該在每個作用域開始時聲明變數和函數。
7、柯里化
柯里化,即Currying,可以是函數變得更加靈活。我們可以一次性傳入多個參數調用它;也可以只傳入一部分參數來調用它,讓它返回一個函數去處理剩下的參數。1.varadd=function(x){
2.returnfunction(y){
3.returnx+y;
4.};
5.};
6.
7.console.log(add(1)(1));//輸出2
8.
9.varadd1=add(1);
10.console.log(add1(1));//輸出2
11.
12.varadd10=add(10);
13.console.log(add10(1));//輸出11
代碼中,我們可以一次性傳入2個1作為參數add(1)(1),也可以傳入1個參數之後獲取add1與add10函數,這樣使用起來非常靈活。
8、apply,call與bind方法
JavaScript開發者有必要理解apply、call與bind方法的不同點。它們的共同點是第一個參數都是this,即函數運行時依賴的上下文。
三者之中,call方法是最簡單的,它等價於指定this值調用函數:1.varuser={
2.name:"RahulMhatre",
3.whatIsYourName:function(){
4.console.log(this.name);
5.}
6.};
7.
8.user.whatIsYourName();//輸出"RahulMhatre",
9.
10.varuser2={
11.name:"NehaSampat"
12.};
13.
14.user.whatIsYourName.call(user2);//輸出"NehaSampat"
·apply方法與call方法類似。兩者唯一的不同點在於,apply方法使用數組指定參數,而call方法每個參數單獨需要指定:
·apply(thisArg,[argsArray])1.varuser={
2.greet:"Hello!",
3.greetUser:function(userName){
4.console.log(this.greet+""+userName);
5.}
6.};
7.
8.vargreet1={
9.greet:"Hola"
10.};
11.
12.user.greetUser.call(greet1,"Rahul");//輸出"HolaRahul"
13.user.greetUser.apply(greet1,["Rahul"]);//輸出"HolaRahul"
使用bind方法,可以為函數綁定this值,然後作為一個新的函數返回:1.varuser={
2.greet:"Hello!",
3.greetUser:function(userName){
4.console.log(this.greet+""+userName);
5.}
6.};
7.
8.vargreetHola=user.greetUser.bind({greet:"Hola"});
9.vargreetBonjour=user.greetUser.bind({greet:"Bonjour"});
10.
11.greetHola("Rahul")//輸出"HolaRahul"
12.greetBonjour("Rahul")//輸出"BonjourRahul"
9、memoization
Memoization用於優化比較耗時的計算,通過將計算結果緩存到內存中,這樣對於同樣的輸入值,下次只需要中內存中讀取結果。
1.functionmemoizeFunction(func)
2.{
3.varcache={};
4.returnfunction()
5.{
6.varkey=arguments[0];
7.if(cache[key])
8.{
9.returncache[key];
10.}
11.else
12.{
13.varval=func.apply(this,arguments);
14.cache[key]=val;
15.returnval;
16.}
17.};
18.}
19.
20.
21.varfibonacci=memoizeFunction(function(n)
22.{
23.return(n===0||n===1)?n:fibonacci(n-1)+fibonacci(n-2);
24.});
25.
26.console.log(fibonacci(100));//輸出354224848179262000000
27.console.log(fibonacci(100));//輸出354224848179262000000
代碼中,第2次計算fibonacci(100)則只需要在內存中直接讀取結果。
10、函數重載
所謂函數重載(method
overloading),就是函數名稱一樣,但是輸入輸出不一樣。或者說,允許某個函數有各種不同輸入,根據不同的輸入,返回不同的結果。憑直覺,函數重載可以通過if...else或者switch實現,這就不去管它了。jQuery之父John
Resig提出了一個非常巧(bian)妙(tai)的方法,利用了閉包。
從效果上來說,people對象的find方法允許3種不同的輸入:
0個參數時,返回所有人名;1個參數時,根據firstName查找人名並返回;2個參數時,根據完整的名稱查找人名並返回。
難點在於,people.find只能綁定一個函數,那它為何可以處理3種不同的輸入呢?它不可能同時綁定3個函數find0,find1與find2啊!這里的關鍵在於old屬性。
由addMethod函數的調用順序可知,people.find最終綁定的是find2函數。然而,在綁定find2時,old為find1;同理,綁定find1時,old為find0。3個函數find0,find1與find2就這樣通過閉包鏈接起來了。
根據addMethod的邏輯,當f.length與arguments.length不匹配時,就會去調用old,直到匹配為止。
1.functionaddMethod(object,name,f)
2.{
3.varold=object[name];
4.object[name]=function()
5.{
6.//f.length為函數定義時的參數個數
7.//arguments.length為函數調用時的參數個數
8.if(f.length===arguments.length)
9.{
10.returnf.apply(this,arguments);
11.}
12.elseif(typeofold==="function")
13.{
14.returnold.apply(this,arguments);
15.}
16.};
17.}
18.
19.
20.//不傳參數時,返回所有name
21.functionfind0()
22.{
23.returnthis.names;
24.}
25.
26.
27.//傳一個參數時,返回firstName匹配的name
28.functionfind1(firstName)
29.{
30.varresult=[];
31.for(vari=0;i
32.{
33.if(this.names[i].indexOf(firstName)===0)
34.{
35.result.push(this.names[i]);
36.}
37.}
38.returnresult;
39.}
40.
41.
42.//傳兩個參數時,返回firstName和lastName都匹配的name
43.functionfind2(firstName,lastName)
44.{
45.varresult=[];
46.for(vari=0;i
47.{
48.if(this.names[i]===(firstName+""+lastName))
49.{
50.result.push(this.names[i]);
51.}
52.}
53.returnresult;
54.}
55.
56.
57.varpeople={
58.names:["DeanEdwards","AlexRussell","DeanTom"]
59.};
60.
61.
62.addMethod(people,"find",find0);
63.addMethod(people,"find",find1);
64.addMethod(people,"find",find2);
65.
66.
67.console.log(people.find());//輸出["DeanEdwards","AlexRussell","DeanTom"]
68.console.log(people.find("Dean"));//輸出["DeanEdwards","DeanTom"]
69.console.log(people.find("Dean","Edwards"));//輸出["DeanEdwards"]
以上就是小編今天為大家分享的關於Web前端工程師應該知道的JavaScript的10個難點。希望本篇文章能夠對正在從事Web前端學習的小夥伴們有所幫助。想要了解更多web前端相關知識記得關注北大青鳥Web培訓官網最後祝願小夥伴們工作順利!
原文鏈接:#/a/1190000010371988
❿ ajaxupload.js無法獲取上傳文件
ajaxupload.js是一個開源的實現Ajax文件上傳的jQuery插件,常用於向伺服器上傳文件。如果遇到該插件無法獲取上傳文件的問題,猜鄭可能是以下幾個方面的原因:
1、插件引用錯誤:首先需要確保插件已正確引用,可以檢查HTML代碼或控制台中是否出現引用錯誤或沒有引用相關JS文件的情況。
2、表單設置錯誤:使用ajaxupload.js時,需要將表單對象傳皮兆衫遞給插件以表示文件上傳的上下文。如果表單對象設置有誤,插件可能無法獲取上傳文件。可以確保表單中存在file類型的input,並將其作為參數傳遞給插件。
3、上傳文件格式不正確:如果上傳文件的格式不受支持,則插件可能無法正確獲取上傳文件。可以確保上傳的文件格式與插件支持的格式相同。
4、安全問題限制:有些情況下,安全設置可能會禁止通過JavaScript讀取文件內容,防止網站被黑客攻擊等。可以檢查安全設置以確定是否存在限制。
5、程序服務端問題:如果前面幾個問題都排除了,還是無法獲取上傳文件,則可能是由於程序服務端的設置或代碼實現問題,需要進一步檢查或調試燃腔。