当前位置:网站首页>this指向问题,闭包以及递归
this指向问题,闭包以及递归
2022-07-27 12:54:00 【芋泥丶】
this指向问题
这些 this 的指向,是当我们调用函数的时候确定的。调用方式的不同决定了this 的指向不同
一般指向我们的调用者.
| 函数调用 | this指向 |
|---|---|
| 普通函数调用 | window |
| 构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
| 对象方法调用 | 改方法所属对象 |
| 事件绑定方法 | 绑定事件对象 |
| 定时器函数 | window |
| 立即执行函数 | window |
改变函数内部 this 指向(call、apply、bind)
call方法
call()方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向
应用场景: 经常做继承.
1. 可以调用函数
fn.call()
2.可以改变函数内this指向
var o = {
name: 'andy'
}
function fn(a, b) {
console.log(this);
console.log(a+b)
};
fn(1,2)// 此时的this指向的是window 运行结果为3
fn.call(o,1,2)//此时的this指向的是对象o,参数使用逗号隔开,运行结果为3
3.可以实现继承
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);
}
var son = new Son('lisi', 18, '男');
console.log(son);//输出结果为age: 18 sex: "男" uname: "lisi"
apply方法
apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
应用场景: 经常跟数组有关系
var o = {
name: 'andy'
}
function fn(a, b) {
console.log(this);
console.log(a+b)
};
fn()// 此时的this指向的是window 运行结果为3
fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3
bind方法
bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数
如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind
应用场景:不调用函数,但是还想改变this指向
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
f();//调用新函数 this指向的是对象o 参数使用逗号隔开
call、apply、bind三者的异同
共同点 : 都可以改变this指向
* 不同点:
- call 和 apply 会调用函数, 并且改变函数内部this指向.
- call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
- bind 不会调用函数, 可以改变函数内部this指向
*应用场景
- call 经常做继承.
- apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。
简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。
闭包有三个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
闭包的主要作用: 延伸了变量的作用范围
function fn() {
var num = 10;
function fun() {
console.log(num);
}
return fun;
}
var f = fn();
f();//函数f()可以使用num的数值
闭包比较难理解,这里可以结合以下的案例来加深印象和理解
闭包案例:3秒钟之后,打印所有li元素的内容
html
<ul>
<li>臭豆腐</li>
<li>螺狮粉</li>
<li>榴莲</li>
<li>鲱鱼罐头</li>
</ul>
js
var lis = document.querySelectorAll("li");
for (var i = 0; i < lis.length; i++) {
(function (i) {
setTimeout(function () {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
这里使用立即执行函数将i的值传入函数
闭包案例:计算打车价格
需求分析:
打车起步价13(3公里内),
之后每多一公里增加 5块钱.
用户输入公里数就可以计算打车价格
如果有拥堵情况,总价格多收取10块钱拥堵费
<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 (falg) {
return falg ? total + 10 : total; } } })(); console.log(car.price(5)); // 23 console.log(car.yd(true)); //23 </script>
</body>
递归
什么是递归
递归: 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己, 这个函数就是递归函数
注意: 递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。
利用递归求1~n的阶乘
//利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
function fn(n) {
if (n == 1) {
//结束条件
return 1;
}
return n * fn(n - 1);
}
console.log(fn(4));//24
参数4传入,经过if判断到达return,在经过递归方法在将参数值为3的函数在调用一边,依次类推直到参数n的值为1时输出;
// 利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、21…
// 利用递归函数求斐波那契数列(兔子序列) 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(3));
利用递归遍历数据
// 我们想要做输入id号,就可以返回的数据对象
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: '冰箱',
goods: [{
id: 111,
gname: '海尔'
}, {
id: 112,
gname: '美的'
},
]
}, {
id: 12,
gname: '洗衣机'
}]
}, {
id: 2,
name: '服饰'
}];
//1.利用 forEach 去遍历里面的每一个对象
function getID(json, id) {
var o = {
};
json.forEach(function(item) {
// console.log(item); // 2个数组元素
if (item.id == id) {
// console.log(item);
o = item;
return o;
// 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, 11));
记得一键三连哦

边栏推荐
- Travel notes from July 11 to August 1, 2022
- ONNXRuntime【推理框架,用户可以非常便利的用其运行一个onnx模型】
- How to test and decrypt the encryption interface
- 关于max做动画的一些关键信息(shift+v)
- Realize the basic operations such as the establishment, insertion, deletion and search of linear tables based on C language
- 小程序毕设作品之微信校园洗衣小程序毕业设计成品(3)后台功能
- [training day3] section [greed] [two points]
- Ncnn compilation and use pnnx compilation and use
- 记账软件如何查看收入支出
- SQL tutorial: introduction to SQL aggregate functions
猜你喜欢

深度置信网络(DBN)【经典的DBN网络结构是由若干层 RBM(受限波尔兹曼机)和一层 BP 组成的一种深层神经网络】

纯c手写线程池

The universe has no end. Can utonmos shine the meta universe into reality?

期货公司开户后续会有哪些服务?

特征工程中的缩放和编码的方法总结

阿里最新股权曝光:软银持股23.9% 蔡崇信持股1.4%

基于C语言的LR1编译器设计

井贤栋等蚂蚁集团高管不再担任阿里合伙人 确保独立决策

RSS tutorial: aggregate your own information collection channels, rshub, freshrss, NetNewsWire

在“元宇宙空间”UTONMOS将打开虚实结合的数字世界
随机推荐
【笔记】逻辑斯蒂回归
认知篇----硬件工程师的成才之路之经典
在灯塔工厂点亮5G,宁德时代抢先探路中国智造
使用RecyclerView,实现列表左滑菜单
Chapter3 data analysis of the U.S. general election gold offering project
Selenium eight elements positioning and relative locator
SwiftUI 地图大全之 使用 MapKit 进行搜索
纯c手写线程池
Thinkphp+ pagoda operation environment realizes scheduled tasks
用命令如何返回上级目录
The finished product of wechat campus laundry applet graduation design (1) development outline
将目标检测大尺寸图片裁剪成固定尺寸图片
C#测量工具示意图
平板模切机
软考 系统架构设计师 简明教程 | 软件测试
Gray histogram
Keras深度学习实战——推荐系统数据编码
SQL tutorial: introduction to SQL aggregate functions
Small program completion work wechat campus laundry small program graduation design finished product (2) small program function
SQL教程之 SQL 聚合函数入门教程