函数
# 默认值
概念: 在ES6中函数的参数支持使用默认值,当在调用函数时如果没有给函数传递实参则形参会使用默认值
语法:
function test(x = 1, y = 2) {
console.log(x, y)
}
test() // 1,2
test(null, 1) // null 1
test(15, 16) // 15, 16
test(undefined, 20) // 1, 20 可以使用但不推荐
2
3
4
5
6
7
8
注意
函数中的任意形参都可以包含默认值
传递null并不会使得形参使用默认值, 参数的值将会变成null
传递undefined会使得形参使用默认值
推荐传递了实参前的参数不要使用默认值
设置默认值形参后面的所有形参会被函数的length属性忽略
var a = function (a,b,c,d ) {}
a.length // 4
var a1 = function (a,b,c,d = 2 ) {}
a1.length // 3 忽略 d 只有abc
var a1 = function (a,b = 0,c,d ) {}
a1.length // 1 忽略b之后所有形参 a
2
3
4
5
6
7
8
函数的任何一个形参一旦被
设置默认值,函数在声明初始化时。所有的参数都将变为独立作用域
的参数
function a(x, x, y ) { } // 正确,形参可以重复的定义
function a(x, x, y = 2 ) { } // 错误,所有形参变成了拥有独立作用域的变量。不可以有同名参数
// 观察下面代码
let x = 5
function a(y = x) {
// 正确, 设置了默认值后 y 作用域当前函数作用域内变量。但是赋值给y的x变量作用域函数外部
let x = 1
console.log(y,x)
}
// 函数的默认值是惰性求值,并不是在声明函数时就已经传递了默认值。而是在每次调用时才会调用默认值
a() //等价于 a(x) 5 1
x = 200
a() //等价于 a(x) 200 100,函数每次调用时才会将默认值赋值给形参
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
函数默认值惰性赋值
特性可以实现函数的特定参数不可以为空
function throwErrorOfUndefined(funcName, funcArg) {
throw new Error('函数:'+ funcName+"缺少必传参数'"+funcArg+"'")
}
// 因为是惰性,所以函数在声明时throwErrorOfUndefined不会立即执行
function test (a = throwErrorOfUndefined('test','a')) {
}
test(123) // 因为没有使用默认值,所以默认值也不会被调用
test() // 当你不传参时,函数才会调用默认值
2
3
4
5
6
7
8
9
10
11
作用域就是一个变量的有效范围,在ES6之前js只有函数作用域
和全局作用域
。ES6引入了块级作用域
,在ES6中创建块级作用域最简单方法时使用大括号"{}" (在ES6中代表块)配合拥有块级作用域
的变量let const就可以实现
{
// 大括号代表一个代码块,有自己独立的块级作用域
let a = 7
console.log(a) // 7
var b = 1
console.log(b) // 1
}
console.log(b) // 1
console.log(a) // a is not defined
// 块 使用ES5实现方法 有两种
// 方法一利用函数作用域
(function(a) { console.log(a) })(9)
console.log(a)
// 方法二 使用try catch实现块级作用域
try {
throw 7
} catch (a) {
console.log(a)
}
console.log(a)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ES6函数拥有name,当前函数的函数名
function aaa () {
console.log(this)
}
console.log(aaa.name) // "aaa"
let demo = function () {
}
console.log(demo.name) // ES5 "" ES6 "demo"
2
3
4
5
6
7
8
9
# 严格模式(use strict)
概念:让js代码在严格的条件下执行。非严格模式下的代码很多是不符合逻辑的,严格模式可以让我们的代码更规范(提高编译效率,消除语法不严谨不合理)。也为js的升级做好铺垫。
语法:声明严格模式 将"use strict"
字面量声明在文档的头部
函数的外部
函数的内部(ES6不允许)
"use strict" //正确 写在外部
function a(x, y ) {
"use strict" // 正确,ES5允许将 "use strict"写到函数内部
}
function a(x, y = 5) { // 错误 ES6 语法中不允许将 "use strict"写到函数内部
"use strict"
}
// 为什么在ES6中 "use strict" 不能写在函数内部
// 我们看下面的代码,因为在ES6中函数的默认值是惰性赋值的,
// 在函数的声明时8进制数077 不会立即赋值 "use strict" 没有办法检测到这里的问题
function a( y = 077) {
"use strict"
return y
}
// 当调用该函数时 8进制先赋值再执行 "use strict" 不符合开发需求的
// ES6为了避免这些问题规定 "use strict" 不能写在 es6的函数内部
a()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
提示
注意 严格模式规范
// 不能使用未声明的变量
a = 7 // Error
// 不能删除对象的属性,不能删除不允许删除的属性
var x = 7
delete x // Error
delete Object.prototype //Error
// 不允许变量重命名
var a = 1
var a = 2 // Error
function (x,x) {} // Error
//不允许使用八进制
var num = 070 // Error
// 不允许使用转义符
var ascii = \010 // Error
// 不允许修改只读属性 不允许对只有get方法的属性进行复制
const person = {};
Object.defineProperty(object1, 'name', {
value: "小明",
writable: false // 是否允许修改该属性 false不允许 true允许
});
person.name = "小刚" // Error
const person {
name: '小王',
get age() {return 18}
}
person.age = 12 // Error
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 不允许声明变量名为关键字的变量
var eval = 1 // Error
var arguments = 2 // Error
var let = 3 // Error
var static = 4 // Error
var public = 5 // Error
var private = 5.1 // Error
var protected = 5.2 // Error
var package = 6 // Error
var interface = 7 // Error
var implements = 8 // Error
var yield = 9 // Error
// eval 作用域独立
eval("var a =10086")
console.log(a)// undefined
// 不允许this 指向全局对象
"use strict"
function aaa () {
console.log(this)
}
aaa() // undefined
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 案例 Object.defineProperty
的使用
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
let obj = {
name: '小于',
age: 40,
address: 'bj',
hobby: ['抽烟', '喝酒', '烫头']
}
Object.defineProperty(obj, 'hobby', {
enumerable: false,
writable: true
})
for (key in obj) {
console.log(key)
}
obj.hobby = ['睡觉']
console.log(obj)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 箭头函数
概念: 在ES6中允许使用 => 形式声明一个函数
语法:
function a (x,y) {
return x + y + 1
}
// 上面的函数就等等价于下面的箭头函数
let a = (x, y) => x + y + 1
2
3
4
5
注意
箭头函数不能直接设置函数名,只能将箭头函数以赋值的形式传递给变量
若箭头函数 => 符号后
没有跟大括号
则箭头函数会将 => 后面的代码自动return
(注意没有大括号的箭头函数只使用于函数内部只有一行js表达式函数), 如果箭头函数包含大括号
, 则默认return功能会被取消
let a = (x, y) => x + y
let a = (x, y) => {
let result = x + y + 1
// 因为当前箭头函数包含大括号,导致自动return功能被取消
// 这时必须使用return 返回特定的值
return result
}
// 如果箭头函数使用默认return功能返回一个对象,必须用()将对象包含
let a = (name, age) => ({name: name, age: age})
2
3
4
5
6
7
8
9
10
- 若箭头函数有且仅有一个参数,则参数的()可以被省略
let func = (age) => age >= 18
// 等价于
let func = age => age >= 18
2
3
4.箭头函数自身
没有this。函数内部的this指向这段代码当前的作用域。
例 下面的代码中在setTimeout中使用箭头函数,箭头函数内部的this指向的是声明这段代码的作用域对象
,而不是
window对象
function Cat(name) {
this.name = name
this.sayHello = function () {
console.log('Meow !')
// 如果是普通函数 setTimeout中的this应该指向window
// 而箭头函数指向当前代码的作用域
setTimeout(() => console.log('你好,我叫' + this.name), 500)
}
}
let cat = new Cat('旺财')
cat.sayHello()
// 对象的方法不要使用箭头函数
let cat1 = {
name: '阿橘',
sayHello: () => {
// 因为对象是全局声明的,他的作用域就是全局
// 这里的this就是全局对象
console.log(this)
}
}
cat1.sayHello() // window
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
箭头函数不能作为构造函数配合new 关键字使用。箭头函数本身就
没有实例
箭头函数没有
arguments
对象
function test (x,y) {
// 伪数组,包含了当前函数的所有实参
console.log(arguments) // Arguments[1,2,8,0,4,5,9,7,callee]
}
test(1,2,8,0,4,5,9,7)
let test = (x,y) => {
console.log(arguments) // Error!箭头函数没有arguments
}
test(1,2,8,0,4,5,9,7)
2
3
4
5
6
7
8
9
10
11
12
13
- 箭头函数不能作为Generator函数 优势
- 简化 js 回调函数
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100)
}
$.ajax({
url: "test.html",
context: document.body,
success: () => $(this).addClass("done")
});
[1, 2, 3, 4, 5].forEach(item => console.log(item));
2
3
4
5
6
7
8
9
10
- 简化
柯里化
函数 函数一次只能接受一个参数
function getPerson(name, age, address) {
return {
name: name,
age: age,
address: address
}
}
getPerson('小明',18, 'gz')
function getPerson(name) {
return function (age) {
return function (address) {
return {
name: name,
age: age,
address: address
}
}
}
}
// ES6 箭头函数简化柯里化函数
let getPerson = name => age => address => ({
name: name,
age: age,
address: address
})
getPerson('小明')(18)('gz')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29