函数
开启严格模式
1,用 " use strict"; 语句为整个脚本(即:script标签)开启严格模式;在<script>标记的第一行写上"use strict";语句;
在IE10 以上的版本才会识别" use strict";语句启用严格模式,而IE10以下无法识别,当成个字符串,不进行操作;
2,用 " use strict “; 语句只为函数加上严格模式,只需要在函数体首行写上"use strict”;语句;
严格模式与普通模式对比发生了那些变化
在变量方面的变化:
1,我们的变量名必须先声明再使用;例:不可直接 " 变量名 =值;"而要用var先去声明;
2,我们不能随意删除已经声明好的变量;例:不可“var num=10; delete num;”
在this指向方面的变化:
3,严格模式下全局作用域中函数的this指向的是undefined不再是window ;
4,严格模式下,如果构造函数不加new调用,this会指向undefined导致了报错;
5,严格模式下,定时器的this还是被默认设置指向window;
6,事件,对象还是指向调用者;
在函数方面的变化:
7,函数括号中的参数不允许重名;
8,不允许在非函数作用域的作用域中声明函数;即:一个函数的内部可以声明另一个函数,而不能在if块,for块等作用域中声明函数;
高阶函数
高阶函数就是对其它函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出;
函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用,最典型的就是作为回调函数;
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数;
简单理解:闭包是一个函数,它的作用域内可以访问另外一个函数内部的局部变量;
1,一个函数有另一个函数在它内部声明,如果内部函数使用了外部函数中的变量,那么就产生了闭包现象,这个内部函数被称为闭包函数,闭包函数可以直接使用外部函数中的变量;
2,两个并列声明的函数如何利用闭包函数来在一个函数作用域中使用另一个函数中的局部变量,一个函数声明一个内部函数(这个函数使用外部函数的变量)并把这个函数作为返回值传出,然后用一个全局变量接收保存,然后在另一个函数中使用这个全局变量;
变量作用域
变量热气作用域的不同分为两种:全局变量和局部变量;
1,函数内部可以作用全局变量;
2,函数外部不可以使用局部变量;
3,当函数执行完毕,本作用域内局部变量就会销毁;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>闭包</title>
</head>
<body>
<script>
//1,外部函数和内部函数
function fun() {
var num = 10;
function fn() {
console.log(num);//fn函数使用了fun函数的num变量,产生了闭包现象,fn就是闭包函数
}
return fn;
}
var f = fun();//用全局变量f接收fn闭包函数
//2,fun和funX为并列声明的函数
function funX() {
f();//此处便在funX函数的作用域中使用了fun函数中的局部变量num
}
funX();//调用函数达到实际效果(funX函数的作用域中使用了fun函数中的局部变量num)
/*
闭包的主要作用:延伸了变量的作用范围
*/
</script>
</body>
</html>
运行后控制台上显示了10,如下:
实例:打车价格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算打车价格</title>
<!-- 打车起步价13(三公里内),之后多一公里增加5块钱,用户输入公里数就可以计算打车价格
如果有拥堵情况,总价格多收取10块钱拥堵费
-->
</head>
<body>
<script>
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));
console.log(car.price(1));
console.log(car.yd(false));
</script>
</body>
</html>
闭包总结
1,闭包是一个函数;
2,闭包的作用是延伸变量的作用范围;
递归
什么是递归
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数;
简单理解:递归函数内部自己调用自己;
递归函数的作用和循环效果一样;
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须加退出条件return 。
实例1:递归求阶乘值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归_阶乘</title>
<!-- 求1*2*3*...*n 阶乘值 -->
</head>
<body>
<script>
function fun(n) {
if (n == 1) {
return 1;
}
return n * fun(n - 1);
}
/* 详细思路:假如用户输入使n=3
return 3*fun(2);->return 3*(2*fun(2-1));->return 3*2*1;->return 6;
*/
</script>
</body>
</html>
实例2:用户输入一个n就输出第n项对应的兔子序列值。
信息:斐波那契数列(黄金数列,兔子数组,斐氏数列,神秘数列,神奇数列):1,1,2,3,5,8,13,21,34…f(n-1)+f(n-2)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>求第n项上的斐波那契数列上对应的序列值</title>
</head>
<body>
<script>
function f(n) {
if (n == 1 || n == 2) {
return 1;
}
return f(n - 1) + f(n - 2);
}
</script>
</body>
</html>
实例3:递归_根据id返回对应的数据对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归_根据id返回对应的数据对象</title>
</head>
<body>
<script>
var data = [{
id: 1,
name: "家电",
goods: [{ id: 11, gname: "冰箱" }, {
id: 12,
gname: "洗衣机"
}]
}, {
id: 2,
name: "服饰"
}
];
//我们想要做输入id号,就可以返回数据对象;
//1,利用forEach去遍历里面的每个对象;
var o = {};//接收函数输出的内容
function getID(json, id) {
json.forEach(function (item) {//2个数组元素
if (item.id == id) {
console.log(item);
o = item;
//2,我们想要里层的数据 11,12可以利用递归函数
//里面应该有goods这个数组并且数组的长度不为0
} else if (item.goods && item.goods.length > 0) {
o = getID(item.goods, id);
}
return o;
})
}
console.log(getID(data, 1));
console.log(getID(data, 2));
console.log(getID(data, 11));
console.log(getID(data, 12));
</script>
</body>
</html>
浅拷贝和深拷贝
1,浅拷贝只是拷贝一层(栈内存中内容),更深层次对象级别的只拷贝引用;
2,深拷贝拷贝多层,每一级别的数据都会拷贝;
浅拷贝的语法糖:
Object.assign(target,…sources);
target :用来接收的对象名,变量名或函数名;
sources :提供被拷贝的数据;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浅拷贝和深拷贝</title>
</head>
<body>
<script>
var obj = {
id: 1,
name: "andy"
};
var o = {};
//浅拷贝
for (var k in obj) {
// k 是属性名 obj[k]属性值
o[k] = obj[k];
}
//深拷贝
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
//判断我们的属性值属于那种数据类型
//1,获取属性值 oldobj[k]
var item = oldobj[k];
if (item instanceof Array) {//2,判断这个值是否是数组
newobj[k] = [];
deepCopy(newobj[k], item);
} else if (item instanceof Object) {//3,判断这个值是否是对象
newobj[k] = {};
deepCopy(newobj[k], item);
} else {//4,属于简单数据类型
newobj[k] = item;
}
}
}
deepCopy(o, obj);
console.log(o);
</script>
</body>
</html>