上一篇文章分享了《帶你學習Javascript中的函數進階(一)》,今天繼續學習javascript的函數進階的內容。
文章目錄
1 嚴格模式
1.1 什麼是嚴格模式
JavaScript除了提供正常模式外,還提供了嚴格模式(strict mode)。ES5的嚴格模式是採用具有限制性Javascript變體的一種方式。即在嚴格的條件下運行js代碼。
嚴格模式在IE10以上版本的瀏覽器中才會被支持,舊版本瀏覽器會被忽略。
嚴格模式對正常的javascript語義做了一些更改:
- 消除了Javascrip語法的一些不合理、不嚴謹之處,減少了一些怪異行爲。
- 消除了代碼運行的一些不安全之處,保證代碼運行的安全。
- 提高編譯器效率,增加運行速度。
- 禁用了在ECMAScript的未來版本中可能會定義的一些語法,爲未來新版本的Javascript做好鋪墊。比
如一些保留字:class,enum,export,extends,import,super不能做變量。
1.2 開啓嚴格模式
嚴格模式可以應用到整個腳本或個別函數中。因此在使用時,我們可以將嚴格模式分爲腳本開啓嚴格模式和
爲函數開啓嚴格模式兩種情況
- 爲腳本整個腳本開啓嚴格模式
爲整個腳步文件開啓嚴格模式,需要在所有語句之前做一個特定語句"use strict"
<scirpt>
"use strict"
console.log("這是最嚴格模式")
</scirpt>
- 爲函數開啓嚴格模式
要給某個函數開啓嚴格模式,需要把"use strict";(或’use strict’)聲明放在函數體所有語句前。
<script>
function fn() {
'use strict' //下面的代碼按照嚴格模式進行
}
</script>
3.3 嚴格模式中的變化
嚴格模式對javascript的語
法和行爲,都做了一些改變
- 變量規定
- 在正常模式中,如果一個變量沒有聲明就賦值,默認的事全局變量。
- var 命令聲明,然後再使用
<script>
‘use strict’
num = 10
console.log(num)
</script>
效果如下圖
嚴禁刪除已經聲明的變量。
- 嚴格模式下this指向問題
- 以前在全局作用域函數中的this指向window對象。
- 嚴格模式下全局作用域中函數中的this事undefined。
- 以前構造函數時不加new也可以調用,當普通函數,this指向全局對象。
- 嚴格模式下,如果構造函數不加new調用,this會報錯。 new實例化的構造函數指向創建的對象實例。
- 嚴格模式下,定時器裏的this指向還是window.
- 嚴格模式下,事件、對象還是指向調用者。
- 函數變化
2 高階函數
高階函數是對其他函數進行操作的函數,它接收函數作爲參數或函數作爲返回值輸出。
function fn(callback) {
callback && callback()
}
fn(function(){
alert('lanfeng')
})
function fn() {
return function() {
}
}
fn()
此時fn就是一個高階函數
函數也是一種數據類型,同樣可以作爲參數,傳遞給另外一個參數使用,最典型的就是作爲回調函數
3 閉包
3.1 變量作用域
變量根據作用域的不同分爲兩種:全局變量和局部變量。
3.2 什麼是閉包
閉包指有權訪問另外一個函數作用域中變量的函數。也就是說,一個作用域可以訪問另外一個函數內部的局部變量。
//fn 外面的作用域可以訪問fn內部的局部變量
function fn() {
var num = 10
function fun () {
console.log(num) //可以訪問num
}
return fun
}
var f = fn()
f() //10
//fn 外面的作用域可以訪問fn內部的局部變量
function fn() {
var num = 10
// 返回一個匿名函數
return function() {
console.log(num) //可以訪問num
}
}
var f = fn()
f() //10
閉包的主要作用: 延伸了變量的作用範圍
3.3 閉包案例
- 循環註冊點擊事件
//html
<ul class="nav">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
</ul>
//js
//點擊li輸出當前li的索引
//利用動態田徑屬性方式
var lis = document.querySelector('.nav').querySelectorAll('li')
for(var i=0 ;i<lis.length; i++) {
lis.index = i
lis[i].onclick = function() {
console.log(this.index)
}
}
//利用閉包的方式
var lis = document.querySelector('.nav').querySelectorAll('li')
for(var i=0 ;i<lis.length; i++) {
(function(i) {
lis[i].onclick = function() {
console.log(i)
}
})(i)
}
- 循環中的setTimeout()
//html
<ul class="nav">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
</ul>
//js
//利用閉包
var lis = document.querySelector('.nav').querySelectorAll('li')
for(var i=0 ;i<lis.length; i++) {
(function(i){
setTimeout(function() {
console.log(lis[i].innerHTML)
},3000)
})(i)
}
- 計算打車價格
var car = (function() {
var start = 13;
var total = 0;
return {
//正常價格
price: function(n) {
if(n <= 3) {
total = start
} else {
total = start + (n-3)* 5
}
return total;
},
// 擁堵之後
yd: function(flag) {
flag? total+ 10 :total
}
}
})()
console.log(car.price(5))
console.log(car.yd(true))
3.4 閉包總結
- 閉包是什麼?
閉包就是一個函數(一個作用域可以訪問另外一個函數的局部變量)
- 閉包的作用是什麼?
延伸變量的作用範圍
4 遞歸
4.1 什麼是遞歸
如果一個函數在內部可以調用其本身,那麼這個函數就是遞歸函數。
遞歸函數的作用和循環效果一樣
由於遞歸很容易發生“棧溢出”(stack overflow),所以必須要加退出條件 return
4.2 利用遞歸求數學題
- 求123…*n
function fn(n) {
if(n = 1) {
return 1
}
return n * fn(n-1)
}
console.log(fn(3)) // 6
4.3 利用遞歸求:根據id返回對應的數據對象
var data = [{
id:1,
name:'家電',
goods: [
{
id: 11,
gname: '冰箱'
},
{
id: 12,
gname: '洗衣機'
}
]
},
{
id: 2,
name: '服飾'
}
]
function getObj(arr, id) {
var o = {}
arr.forEach(function(item){
if(item.id === id) {
o= item
} else if(item.goods && item.goods.length>0) {
o =getObj(item.goods, id);
}
})
return o
}
console.log(getObj(data, 1))
5 遞歸
5.1 淺拷貝和深拷貝
- 淺拷貝只是拷貝一層,更深層次對象級別的只拷貝引用。
- 深拷貝拷貝多層,每一級別的數據都會拷貝。
- Object.assign(target, …sources) es6新增方法可以淺拷貝
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
}
var o = {}
for(var k in obj) {
// k是屬性名
o[k] = obj[k]
}
console.log(o)
o.msg.age = 20
console.log(obj) //obj發生變化
//用es6語法糖
Object.assign(o, obj)
//深拷貝,應用遞歸的方法
function deepCopy(newObj, oldObj) {
for(var k in oldObj) {
//判斷我們的屬性值屬於哪種類型
var item = oldObj[k]
// 判斷是否是數組
if(item instanceof Array) {
newObj[k] = []
deepCopy(newObj[k], item)
} else if(item instanceof Object) {
//判斷是否是對象
newObj[k] = {}
deepCopy(newObj[k], item)
} else { // 屬於簡單數據類型
newObj[k] = item
}
}
}
deepCopy(o,obj)
console.log(o)
總結
本篇文章主要分享了函數的嚴格模式、高階函數、閉包、遞歸、深拷貝、淺拷貝等知識點的用法及應用。