js函数进阶
Posted cuter、
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js函数进阶相关的知识,希望对你有一定的参考价值。
一、函数的定义和调用
1.1函数的定义方式
//1.自定义函数
function fn(a, b) {
return a + b;
};
fn(1, 2);
//2.函数表达式定义
var fn = function() {
};
//3.利用 new Function (‘参数1’,‘参数2’,‘参数3’)
var f = new Function('a', 'b', 'console.log(a+b)');
f(1, 2);
//4.所有函数都是 Function的实例(对象)
//5.函数也属于对象
console.log(f instanceof Object);
1.2函数的定义方式
1.普通函数
function fn() {
}
fn();
fn.call();
2.对象的方法
var obj = {
sayhi: function() {
}
}
obj.sayhi();
3.构造函数
function Fn() {
}
new Fn()
4.绑定事件函数
btn.onclick = function() {
}
5.定时器函数
setInterval(function() {
})
6.立即执行函数
(function() {
})()
(function() {
}())
二、this
2.1this的指向问题
2.1.1call方法
//1.call
var o = {
name: 'andy'
}
function fn(a, b) {
console.log(this);
console.log(a + b);
}
fn.call(o, 1, 2);
//call第一个可以调用函数 第二个可以改变函数内的this指向
//call的主要左右可以实现继承
function Father(uname, age, sex) {
this.uname = uname;
this.age = age;
this.sex = sex;
}
function Son(uname, age, sex) {
Father.call(this, uname, age, sex);
//this 继承父类的属性
}
var son = new Son('刘德华', 18, '男');
console.log(son);
2.1.2apply方法
//1.apply
var o = {
name: 'andy'
};
function fn(arr) {
console.log(this);
console.log(arr); //xu
};
fn.apply(o, ['xu']);
//1.也是调用函数 可以改变函数内部的this指向
//2.但是他的参数 必须是数组(伪数组)
//3.apply的主要应用 比如说我们可以利用apply借助于数学内置对象求最大值
//Math.max()
var arr = [1, 6, 99, 3, 45];
var max = Math.max.apply(Math, arr); //因为是Math调用了max 所以要指向Math
var min = Math.min.apply(Math, arr); //因为是Math调用了max 所以要指向Math
console.log(max); //99
console.log(min); //1
2.1.3bind方法
<button>点击</button>
<script>
// var o = {
// name: 'xu'
// };
// function fn(a, b) {
// console.log(this);
// console.log(a + b); //3
// };
// var f = fn.bind(o, 1, 2);
// f();
//1.不会调用原来的函数 可以改变原来函数内部的this指向
//2.返回的是原函数改变this之后产生的新函数
//3.如果有的函数不需要立即调用 但是又想改变函数内部的this指向 此时用bind方法
//我们有一个按钮 点击后就禁用这个按钮 3秒之后就可以解除禁用
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
this.disabled = true; //这个this指向的是btn这个按钮
//var that = this;
setTimeout(function() {
//定时器里面的函数指向的是window对象
//that.disabled=false;
this.disabled = false;
}.bind(this), 3000); //这个this指向的是btn这个对象
});
2.2bind 、call、apply方法总结
三、严格模式
3.1什么是严格模式
3.2开启严格模式
<!-- 为整个脚本script标签开启严格模式 -->
<script>
'use strict'
//下面的js代码就会按照严格模式执行代码
</script>
<script>
(function() {
'use strict';
})();
</script>
2.为函数开启严格模式
<script>
//为函数开启严格模式
function fn() {
//此时只是给fn 开启了严格模式 下面的代码按照严格模式执行
'use strict';
}
function fun() {
//还是按照普通模式执行
}
</script>
3.3严格模式中的变化
<script>
'use strict';
var num = 10;
console.log(num);
//我们不能随意删除已经声明好的变量
delete num;
//在严格模式下 全局作用域中 函数的this指向的是 undefined
function fn() {
console.log(this); //undefined
};
fn();
// 严格模式下 构造函数不加new调用 ,this会报错
function Star() {
this.sex = '男';
};
// Star();
// console.log(window.sex);
var ldh = new Star();
console.log(ldh.sex); //男
</script>
四、高阶函数
五、闭包
5.1变量作用域
5.2什么是闭包
//闭包:我们fun这个函数作用域 访问了另外一个函数fn里面的局部变量 num
//fn是闭包
function fn() {
var num = 10;
function fun() {
console.log(num); //10
}
fun();
}
fn();
5.3闭包的作用
延伸了作用范围
<script>
//闭包:我们fun这个函数作用域 访问了另外一个函数fn里面的局部变量 num
//fn是闭包
//我们fn外面的作用域可以访问fn内部的局部变量
function fn() {
var num = 10;
function fun() {
console.log(num); //10
}
return fun();
}
var f = fn();
f();
//类似于
var f = function fun() {
console.log(num); //10
};
</script>
5.3.1闭包案例 点击li获得索引号
//闭包应用 点击li输出当前li的索引号
//1.我们可以利用动态添加属性的方法
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
console.log(i);
lis[i].index = i;
}
}
//2.利用闭包的方式得到当前li的索引号
for (var i = 0; i < lis.length; i++) {
//利用for循环创建了四个立即执行函数
//立即执行函数也称为小闭包 因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
// console.log(i);
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
5.3.2闭包案例 定时器闭包
<ul class="nav">
<li>榴莲</li>
<li>饺子</li>
<li>你好</li>
<li>苹果</li>
<li>香蕉</li>
</ul>
<script>
//闭包应用 3秒钟之后,打印所有的li元素
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)
}
</script>
5.3.3闭包案例 计算打车价格
<script>
//闭包应用-计算打车价格
//打车起步13(3公里内) 之后每一公里加五块钱 用户输入公里数可以计算打车价格
//如果有拥堵情况,总价多收取10块钱拥堵费
//function fn() {};
//fn();
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) { //拥堵之后的费用
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5)); //23
console.log(car.yd(true)); //33
console.log(car.price(1)); //13
console.log(car.yd(false)); //13
</script>
六、递归
6.1递归
//递归函数:函数内部自己调用 ,这个函数就是递归函数
var num = 1;
function fn() {
console.log('我要打印6句话');
if (num == 6) {
return; //递归里面必须加退出条件
}
num++;
fn();
}
fn();
6.1.1利用递归求 1到n的阶乘
script>
//利用递归函数求1~n的阶乘 1* 2 *3*...n
function fn(n) {
if (n === 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));//6
//详细思路 假如用户输入3
// return 3 * fn(2)
// return 3 * (2*fn(2-1))
// return 3 * (2*fn(1))
// return 3 * (2*1)
// return 6
6.1.2利用递归求 斐波那契数列
//利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、21...
//用户输入一个数字n就可以求出这个数字对应的斐波那契数列值
//我们只需要知道用户输入的n的前面两项(n-1 n-2) 就可以计算出n的序列值
function fb(n) {
if (n === 1 || n === 2) {
return 1;
}
return fb(n - 1) + fb(n - 2);
}
console.log(fb(5));//5
6.1.3利用递归求 id商品号
<script>
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: "冰箱"
}, {
id: 12,
gname: "洗衣机"
}]
}, {
id: 2,
name: "服饰"
}];
//1.利用foreach遍历里面每一个对象
function getId(json, id) {
var o = {}
json.forEach(function(item) {
if (item.id === id) {
// console.log(item);
o = item;
return item;
//我们想要得到里层的数据,可以利用递归函数
//里面应该有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(datajs代码片段: utils/lcoalStorage/cookie