[TOC]
# 1. this关键字
JavaScript中的this指向问题,有时候会让人难以捉摸,随着学习的深入,我们可以逐渐了解,函数内部的this有如下几个特点:
1. 函数在定义的时候this是不确定的,只有在调用的时候才可以确定
2. 一般函数直接执行,内部this指向全局window
3. 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
4. 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过new关键字来调用,从而实现实例化
| 调用方式 | 非严格模式 | 备注 |
| --- | --- | --- |
| 普通函数调用 | window | 严格模式下是 undefined |
| 构造函数调用 | 实例对象 | 原型方法中 this 也是实例对象 |
| 对象方法调用 | 该方法所属对象 | 紧挨着的对象 |
| 事件绑定方法 | 绑定事件对象 | |
| 定时器函数 | window |
# 2. call、apply、bind函数
call、apply、bind函数可以将`this`指向规定的对象。
<mark>1. call函数</mark>
语法:
```js
fun.call(thisArg[, arg1[, arg2[, ...]]]) //[ ] 表示可选, fun为函数
```
注意:该方法的作用和 apply() 方法类似,只有一个区别,就是 call() 方法接受的是若干个参数的列表,而 apply() 方法接受的是一个包含多个参数的数组。
- `thisArg`
+ 在 fun 函数运行时指定的 this 值
+ 如果指定了 null 或者 undefined 则内部 this 指向 window
+ 值为原始值(数字,字符串,布尔值)的`this`会指向该原始值的自动包装对象。
- `arg1, arg2, ...`
* 指定的参数列表
* 返回值
* 返回值是你调用的方法的返回值,若该方法没有返回值,则返回`undefined`
```js
function fun1(x, y) {
console.log(x+y);
}
var message = {
name: "李明",
age: 24
}
// call函数调用了fun1函数
// fun1的this指向了message对象
// 100,200两个实参对应fun1的两个形参
fun1.call(message, 100, 200); // 300
```
<mark>2. apply函数</mark>
语法:
```js
fun.apply(thisArg, [argsArray])
```
`apply()` 与 `call()` 非常相似,不同之处在于提供参数的方式。`apply()` 使用参数数组而不是一组参数列表。例如:
```js
fun.apply(this, ['eat', 'bananas'])
```
<mark>3. bind函数</mark>
bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。
当 ```fun.bind(thisArg,..)时,``` ```fun的this``` 绑定到 bind() 的第一个参数,该参数不能被重写。绑定函数被调用时,bind() 也接受预设的参数提供给原函数,即```fun```。
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 ```this``` 值被忽略,同时调用时的参数被提供.
```js
function f1(x, y) {
console.log(x+y);
}
var obj = {
age: 10,
getAge: function() {
console.log(this.age);
}
}
// f1的this指向了obj
// 100,200两个实参对应f1中的两个形参
// bind函数返回了ff函数,结构与f1一样
// bind函数并没有调用f1函数,所以f1.bind不会执行f1的代码
var ff = f1.bind(obj, 100, 200); // ff就是绑定函数
ff(); // 300 调用ff时上面的那两个实参100,200也提供给了ff
```
语法:
```js
fun.bind(thisArg[, arg1[, arg2[, ...]]])
```
- thisArg
+ 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。
- arg1, arg2, ...
+ 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
返回值:返回由指定的this值和初始化参数改造的原函数拷贝。
实例1:
```js
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象
// 新手可能会被全局的x变量和module里的属性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
```
实例2:
```js
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom(); // 一秒钟后, 调用'declare'方法
```
- js应用场景
- js组成
- js书写位置
- 浮点数精度问题
- undefined与null的区别
- 数据类型转换
- 运算符优先级
- 代码调试
- 函数
- 函数的定义和调用
- 函数的return细节
- 函数是一种数据类型
- this的指向
- 函数成员
- 函数闭包
- 作用域
- 预解析
- js对象
- 对象的创建与调用
- new关键字
- this关键字
- 构造函数创建对象
- 事件
- 数据类型
- 继承
- 杂项
- 如何阻止标签的默认行为
- 为一个标签绑定或移除任何一个事件
- 如何阻止事件的冒泡行为
- 事件的三个阶段
- 移动元素的条件
- 匀速动画函数封装
- 变速动画函数封装
- 获取元素的css属性值
- 数据类型判断方法
- 创建对象的7种写法
- 如何继承
- 为js内置对象添加原型函数
- 将局部变量转换为全局变量
- call函数的用法
- 沙箱
- 浅拷贝
- 深拷贝
- 对象赋值会改变对象
- 解析URL中的字符串
- 格式化日期
- 获取当前浏览器类型
- Vue3.x
- 调式工具Vue Devtools