目录
一、函数的定义和调用
1、函数的定义方式
①自定义函数(命名函数) ②函数表达式(匿名函数)③new Function()(效率低,很少使用)
所有函数都是Function的实例对象
,函数也属于对象
2、函数的调用方式
6种函数:① 普通函数 ②对象的方法 ③构造函数 ④绑定事件函数 ⑤定时器函数 ⑥立即执行函数
// 调用方式
// 1.普通函数
function fn(){};
fn();
fn.call()
// 2.对象的方法
var obj = {
sayHi: function () {},
};
obj.sayHi();
// 3.构造函数
function Star() {}
new Star();
// 4.绑定事件函数
btn.onclick = function () {};
// 5.定时器函数
setTimeout(function () {}, 1000);
// 6.立即执行函数
(function () {})();
二、this
1、this指向
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器 | window |
立即执行函数 | window |
2、改变this指向
JS中改变this指向的方法有:① bind()
②call()
③apply()
方法
《1》call()(调用函数)
fun.call(thisArg, arg1, arg2, ...);
// thisArg:当前调用函数this的指向对象
// arg1,arg2:传递的其他参数
返回值:函数的返回值
使用场景:改变this指向并且调用该函数,比如继承(返回值是函数的返回值)
《2》apply()(跟数组相关)
fun.apply(thisArg, [argsArray]);
// argsArray:传递的值,必须包含在数组里面
返回值:函数的返回值
使用场景:主要跟数组有关系,比如借助于数学对象实现数组最大值最小值
《3》bind()(不调用函数)
fun.bind(thisArg, arg1, arg2, ...);
返回值:指定的 this值和初始化参数改造的原函数拷贝
使用场景:只想改变this指向,不调用该函数,比如改变定时器内部this指向
三、严格模式
JS除了提供正常模式外,还提供了严格模式(strict mode),严格模式IE10以上支持
开启严格模式的分类:① 为脚本开启严格模式 ② 为函数开启严格模式
1、为脚本开启严格模式
在所有语句之前放一个特定语句“use strict”;(或‘use strict’;)
<script>
"use strict";
</script>
有的 script 基本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他 script 脚本文件。
<script>
(function (){
"use strict";
var num = 10;
function fn() {}
})();
</script
2、为函数开启严格模式
要把“use strict”; (或 ‘use strict’; ) 声明放在函数体所有语句之前
function fn(){
"use strict";
return "这是严格模式。";
}
3、严格模式中的变化
《1》变量规定
① 变量都必须先用var 命令声明,然后再使用
②严禁删除已经声明变量
《2》this指向
① 严格模式下全局作用域中函数中的 this 是 undefined
② 如果构造函数不加new调用, this 指向的是undefined 如果给他赋值则会报错
《3》函数变化
① 函数不能有重名的参数
② 函数必须声明在顶层
更多严格模式要求:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode
四、高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数
或 将函数作为返回值输出
。
// 接收函数作为参数
function fn(callback) {
callback && callback();
}
fn(function () {});
// 函数作为返回值输出
function fn() {
return function () {};
}
fn();
典型的高阶函数应用:回调函数
五、闭包
变量根据作用域不同分为两类:① 全局变量 ② 局部变量
函数外部不能使用局部变量,当函数执行完毕,本作用域的局部变量会销毁
1、闭包(closure)
闭包:有权访问另一个函数作用域中变量
的函数
function fn() { // fn就是闭包函数
var num = 10;
function fn2() {
console.log(num);
}
fn2();
}
fn();
2、在chrome中调试闭包
3、闭包的作用
延时变量的作用范围
function fn() {
var num = 10;
return function {
console.log(num); // 10
}
}
var f = fn();
f()
4、思考题
// 思考题 1:
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()());
// 类似于
var f = object.getNameFunc();
var f = function() {
return this.name;
}
f();
// 思考题 2:
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name;
};
},
};
console.log(object.getNameFunc()());
六、递归
递归函数:在函数内部可以调用其本身
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
。
1、求123*…*n的阶乘
function fn(n) {
if (n == 1) {
return 1;
}
return n * fn(n - 1);
}
2、求斐波那契数列
function fn(n) {
if (n < 3) {
return 1;
}
return fn(n - 2) + fn(n - 1);
}
3、根据ID返回对象的数据
var data = [
{
id: 1,
name: "家电",
goods: [
{
id: 11,
gname: "冰箱",
goods: [
{
id: 111,
gname: "海尔",
},
{
id: 112,
gname: "美的",
},
],
},
{
id: 12,
gname: "洗衣机",
},
],
},
{
id: 2,
name: "服饰",
},
];
function fn(data, id) {
var a = {};
data.forEach((item) => {
if (item.id == id) {
a = item;
} else if (item.goods && item.goods.length > 0) {
a = fn(item.goods, id);
}
});
return a;
}
console.log(fn(data, 11));