亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript函數的一些注意點

2019-11-08 01:18:55
字體:
來源:轉載
供稿:網友

參考:廖雪峰老師的javascript教程

變量作用域

變量提升

Javascript的函數定義有個特點,它會先掃描整個函數體的語句,把所有申明的變量“提升”到函數頂部

'use strict';function foo() { var x = 'Hello, ' + y; alert(x); var y = 'Bob';}foo();

雖然是strict模式,但語句var x = ‘Hello, ’ + y;并不報錯,原因是變量y在稍后申明了。但是alert顯示Hello, undefined,說明變量y的值為undefined。這正是因為JavaScript引擎自動提升了變量y的聲明,但不會提升變量y的賦值。

全局作用域

不在任何函數內定義的變量就具有全局作用域。實際上,JavaScript默認有一個全局對象window,全局作用域的變量實際上被綁定到window的一個屬性

'use strict';var course = 'Learn JavaScript';alert(course); // 'Learn JavaScript'alert(window.course); // 'Learn JavaScript'

因此,直接訪問全局變量course和訪問window.course是完全一樣的。

由于函數定義有兩種方式,以變量方式var foo = function () {}定義的函數實際上也是一個全局變量,因此,頂層函數的定義也被視為一個全局變量,并綁定到window對象

我們每次直接調用的alert()函數其實也是window的一個變量

JavaScript實際上只有一個全局作用域。任何變量(函數也視為變量),如果沒有在當前函數作用域中找到,就會繼續往上查找,最后如果在全局作用域中也沒有找到,則報ReferenceError錯誤。

名字空間

全局變量會綁定到window上,不同的JavaScript文件如果使用了相同的全局變量,或者定義了相同名字的頂層函數,都會造成命名沖突,并且很難被發現。

減少沖突的一個方法是把自己的所有變量和函數全部綁定到一個全局變量中。例如:

// 唯一的全局變量MYAPP:var MYAPP = {};// 其他變量:MYAPP.name = 'myapp';MYAPP.version = 1.0;// 其他函數:MYAPP.foo = function () { return 'foo';};

把自己的代碼全部放入唯一的名字空間MYAPP中,會大大減少全局變量沖突的可能。

許多著名的JavaScript庫都是這么干的:jQuery,YUI,underscore等等。

局部作用域

由于JavaScript的變量作用域實際上是函數內部,我們在for循環等語句塊中是無法定義具有局部作用域的變量的:

'use strict';function foo() { for (var i=0; i<100; i++) { // } i += 100; // 仍然可以引用變量i}

為了解決塊級作用域,ES6引入了新的關鍵字let,用let替代var可以申明一個塊級作用域的變量:

'use strict';function foo() { var sum = 0; for (let i=0; i<100; i++) { sum += i; } i += 1; // SyntaxError}

常量

由于var和let申明的是變量,如果要申明一個常量,在ES6之前是不行的,我們通常用全部大寫的變量來表示“這是一個常量,不要修改它的值”

var PI = 3.14;

ES6標準引入了新的關鍵字const來定義常量,const與let都具有塊級作用域

'use strict';const PI = 3.14;PI = 3; // 某些瀏覽器不報錯,但是無效果!PI; // 3.14

方法 在一個對象中綁定函數,稱為這個對象的方法。

在JavaScript中,對象的定義是這樣的:

var xiaoming = { name: '小明', birth: 1990};

但是,如果我們給xiaoming綁定一個函數,就可以做更多的事情。比如,寫個age()方法,返回xiaoming的年齡:

var xiaoming = { name: '小明', birth: 1990, age: function () { var y = new Date().getFullYear(); return y - this.birth; }};xiaoming.age; // function xiaoming.age()xiaoming.age(); // 今年調用是25,明年調用就變成26了

在一個方法內部,this是一個特殊變量,它始終指向當前對象,也就是xiaoming這個變量。所以,this.birth可以拿到xiaoming的birth屬性。

讓我們拆開寫:

function getAge() { var y = new Date().getFullYear(); return y - this.birth;}var xiaoming = { name: '小明', birth: 1990, age: getAge};xiaoming.age(); // 25, 正常結果getAge(); // NaN

單獨調用函數getAge()怎么返回了NaN?請注意,我們已經進入到了JavaScript的一個大坑里。

JavaScript的函數內部如果調用了this,那么這個this到底指向誰?

答案是,視情況而定!

如果以對象的方法形式調用,比如xiaoming.age(),該函數的this指向被調用的對象,也就是xiaoming,這是符合我們預期的。

如果單獨調用函數,比如getAge(),此時,該函數的this指向全局對象,也就是window。

更坑爹的是,如果這么寫:

var fn = xiaoming.age; // 先拿到xiaoming的age函數fn(); // NaN

也是不行的!要保證this指向正確,必須用obj.xxx()的形式調用!

由于這是一個巨大的設計錯誤,要想糾正可沒那么簡單。ECMA決定,在strict模式下讓函數的this指向undefined,因此,在strict模式下,你會得到一個錯誤:

'use strict';var xiaoming = { name: '小明', birth: 1990, age: function () { var y = new Date().getFullYear(); return y - this.birth; }};var fn = xiaoming.age;fn(); // Uncaught TypeError: Cannot read 這個決定只是讓錯誤及時暴露出來,并沒有解決this應該指向的正確位置。

有些時候,喜歡重構的你把方法重構了一下:

'use strict';var xiaoming = { name: '小明', birth: 1990, age: function () { function getAgeFromBirth() { var y = new Date().getFullYear(); return y - this.birth; } return getAgeFromBirth(); }};xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined

結果又報錯了!原因是this指針只在age方法的函數內指向xiaoming,在函數內部定義的函數,this又指向undefined了?。?strong>在非strict模式下,它重新指向全局對象window!)

修復的辦法也不是沒有,我們用一個that變量首先捕獲this

'use strict';var xiaoming = { name: '小明', birth: 1990, age: function () { var that = this; // 在方法內部一開始就捕獲this function getAgeFromBirth() { var y = new Date().getFullYear(); return y - that.birth; // 用that而不是this } return getAgeFromBirth(); }};xiaoming.age(); // 25

用var that = this;,你就可以放心地在方法內部定義其他函數,而不是把所有語句都堆到一個方法中。

apply

雖然在一個獨立的函數調用中,根據是否是strict模式,this指向undefined或window,不過,我們還是可以控制this的指向的!

要指定函數的this指向哪個對象,可以用函數本身的apply方法,它接收兩個參數,第一個參數就是需要綁定的this變量,第二個參數是Array,表示函數本身的參數。

(其實我個人決定就是告訴js調用函數的對象和參數而已)

用apply修復getAge()調用:

function getAge() { var y = new Date().getFullYear(); return y - this.birth;}var xiaoming = { name: '小明', birth: 1990, age: getAge};xiaoming.age(); // 25getAge.apply(xiaoming, []); // 25, this指向xiaoming, 參數為空

另一個與apply()類似的方法是call(),唯一區別是:

apply()把參數打包成Array再傳入;

call()把參數按順序傳入。

比如調用Math.max(3, 5, 4),分別用apply()和call()實現如下:

Math.max.apply(null, [3, 5, 4]); // 5Math.max.call(null, 3, 5, 4); // 5

對普通函數調用,我們通常把this綁定為null。

裝飾器

利用apply(),我們還可以動態改變函數的行為。

JavaScript的所有對象都是動態的,即使內置的函數,我們也可以重新指向新的函數。

現在假定我們想統計一下代碼一共調用了多少次parseInt(),可以把所有的調用都找出來,然后手動加上count += 1,不過這樣做太傻了。最佳方案是用我們自己的函數替換掉默認的parseInt():

var count = 0;var oldParseInt = parseInt; // 保存原函數window.parseInt = function () { count += 1; return oldParseInt.apply(null, arguments); // 調用原函數};// 測試:parseInt('10');parseInt('20');parseInt('30');count; // 3
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩成人在线观看| 日本乱人伦a精品| 国内精品模特av私拍在线观看| 中文字幕免费精品一区| 色噜噜狠狠狠综合曰曰曰88av| 欧美激情精品在线| 亚洲人成伊人成综合网久久久| 欧美一性一乱一交一视频| 国产欧美日韩精品在线观看| 国产精品久久久久久久电影| 国产精品av电影| 日本亚洲精品在线观看| 97精品免费视频| 欧美精品xxx| 三级精品视频久久久久| 美女扒开尿口让男人操亚洲视频网站| 日韩欧美精品中文字幕| 欧美性极品少妇精品网站| 日韩激情在线视频| 欧美性感美女h网站在线观看免费| 欧美性猛交xxxx免费看| 国产一区视频在线| 欧美日韩国产专区| 欧美另类老女人| 一区二区三区www| 亚洲天堂开心观看| 国产精品国产三级国产专播精品人| 欧美丰满少妇xxxxx| 亚洲欧美日韩图片| 色婷婷综合久久久久| 麻豆国产va免费精品高清在线| 欧美激情日韩图片| 日韩精品免费电影| 亚洲无线码在线一区观看| 在线丨暗呦小u女国产精品| 亚洲国产私拍精品国模在线观看| 亚洲综合精品一区二区| 日韩精品在线电影| 色综合久久悠悠| 日韩精品亚洲精品| 久久久午夜视频| 欧美午夜片欧美片在线观看| 国产精品∨欧美精品v日韩精品| 亚洲免费电影在线观看| 日韩美女毛茸茸| 一本一道久久a久久精品逆3p| 自拍视频国产精品| 在线成人免费网站| 亚洲最大的成人网| 色综合导航网站| 日韩禁在线播放| 91国内在线视频| 国产精品黄色影片导航在线观看| 欧美在线观看视频| 欧美电影免费在线观看| 欧美孕妇与黑人孕交| 亚洲视频电影图片偷拍一区| 92裸体在线视频网站| 日韩av电影免费观看高清| 亚洲国产精品va在线观看黑人| 亚洲国产成人精品女人久久久| 亚洲国产精品久久久久久| 亚洲少妇激情视频| 欧美极品少妇全裸体| 欧美日韩国产精品一区二区三区四区| www国产精品com| 国产亚洲精品日韩| 亚洲一区二区久久久久久| 亚洲最大av网站| 日韩精品免费在线| 国产精品com| 中文字幕亚洲色图| 成人免费观看网址| 中文字幕成人精品久久不卡| 91免费视频国产| 亚洲精品720p| 欧美国产一区二区三区| 久久久99免费视频| 国产成人在线视频| 色偷偷av一区二区三区| 国内精品模特av私拍在线观看| 欧美日韩美女在线观看| 精品国产91久久久久久老师| 精品久久香蕉国产线看观看亚洲| 欧美日韩国产专区| 国产丝袜一区二区| 日本精品视频在线观看| 久久久99久久精品女同性| 91探花福利精品国产自产在线| 日韩欧美精品中文字幕| 亚洲情综合五月天| 国产精品久久精品| 久久精品国产欧美激情| 日韩视频免费在线观看| 日韩激情视频在线播放| 亚洲第一视频网站| 久久精品中文字幕一区| 国产精品成人一区二区三区吃奶| 亚洲精品国产精品国产自| 日韩在线观看网址| 欧美体内谢she精2性欧美| 日韩欧美国产视频| 久久久999成人| 亚洲美女精品成人在线视频| 亚洲精品黄网在线观看| 亚洲的天堂在线中文字幕| 国产亚洲精品激情久久| 国产精品精品久久久久久| 久久中文字幕在线| 亚洲天堂第二页| **欧美日韩vr在线| 亚洲人成绝费网站色www| 欧美一级大片在线免费观看| 秋霞成人午夜鲁丝一区二区三区| 欧洲亚洲免费在线| 91成人精品网站| 国产做受高潮69| 日韩精品久久久久久福利| 一区二区中文字幕| www.欧美精品一二三区| 国产精品一区二区三区免费视频| 久久久久久高潮国产精品视| 国产成人福利视频| 久久久久久噜噜噜久久久精品| 亚洲va男人天堂| 欧美福利在线观看| 久久久久久久国产精品| 久久久久久久电影一区| 欧美激情网友自拍| 中文字幕自拍vr一区二区三区| 国产欧美一区二区| 国产精品欧美亚洲777777| 美女精品视频一区| 久久国产精品偷| 中文字幕欧美视频在线| 成人免费视频网址| 日韩在线免费视频| 日韩中文在线视频| 国产精品青草久久久久福利99| 亚洲在线免费视频| 亚洲午夜女主播在线直播| 国产精品99久久久久久www| 欧美精品在线观看91| 97国产在线视频| 91精品视频在线免费观看| 日韩欧美成人网| 亚洲一区第一页| 亚洲专区中文字幕| 狠狠操狠狠色综合网| 亚洲精品xxxx| 日韩精品视频免费在线观看| 在线观看欧美成人| 日韩在线观看免费av| 亚洲激情自拍图| 国产美女高潮久久白浆| 成人444kkkk在线观看| 国产欧美日韩亚洲精品| 欧美日韩第一页| 欧美寡妇偷汉性猛交| 欧美日韩国产一区二区| 一本色道久久综合狠狠躁篇的优点| 狠狠躁天天躁日日躁欧美| 国产亚洲欧洲高清| 亚洲伊人一本大道中文字幕|