JavaScript开发者应懂的33个概念6-this, call, apply 和 bind
目录
- 调用堆栈
- 原始类型
- 值类型和引用类型
- 隐式, 显式, 名义和鸭子类型
- == 与 ===, typeof 与 instanceof
- this, call, apply 和 bind
- 函数作用域, 块级作用域和词法作用域
- 闭包
- map, reduce, filter 等高阶函数
- 表达式和语句
- 变量提升
- Promise async 与 wait
- 立即执行函数, 模块化, 命名空间
- 递归
- 算法
- 数据结构
- 消息队列和事件循环
- setTimeout, setInterval 和 requestAnimationFrame
- 继承, 多态和代码复用
- 按位操作符, 类数组对象和类型化数组
- DOM 树和渲染过程
- new 与构造函数, instanceof 与实例
- 原型继承与原型链
- Object.create 和 Object.assign
- 工厂函数和类
- 设计模式
- Memoization
- 纯函数, 函数副作用和状态变化
- 耗性能操作和时间复杂度
- JavaScript 引擎
- 二进制, 十进制, 十六进制, 科学记数法
- 偏函数, 柯里化, Compose 和 Pipe
- 代码整洁之道
简介
记录一个重新学习javascript的过程 ,文章并不是按顺序写的,写完就会更新目录链接 本篇文章目录是参照 @leonardomso 创立,英文版项目地址在这里
1.js中的this
面向对象语言中 this 表示当前对象的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
- 在方法中,this 表示该方法所属的对象。
- 如果单独使用,this 表示全局对象。
- 在函数中,this 表示全局对象。
- 在函数中,在严格模式下,this 是未定义的(undefined)。
- 在事件中,this 表示接收事件的元素。
this主要应用在:
- 构造函数中的this;
- 普通函数中的this;
- 对象函数中的this;
- call、apply、bind改变this
- 箭头函数中的this
1.1构造函数中的this
以构造函数的形式调用时,this就是新创建的对象
function Person(name) {
this.name = name;
}
const p = new Person('张三');
console.log(p.name);
1.2 普通函数中的this
普通函数中的this 是window ,“use strict”; 严格模式下是undefined
"use strict";
function getVal() {
console.log(this); //window,严格模式下是undefined
}
getVal();
1.3 对象函数
中的this
以方法的形式调用时,this就是调用方法的对象
var person = {
firstName: "张",
lastName : "三",
fullName : function() {
return this.firstName + " " + this.lastName;
}
};
console.log(person.fullName());//张 三
1.4 单独使用this
单独使用 this,则它指向全局(Global)对象。
在浏览器中,window 就是该全局对象为 [object Window]:
严格模式下,如果单独使用,this 也是指向全局(Global)对象。
"use strict";
var x = this;
console.log(x);//window
1.5 事件中的this
在事件中,this 表示接收事件的元素
<button onclick="this.style.display='none'">点我后我就消失了</button>
1.6 箭头函数中的this
箭头函数this的几种解释说法
1.当我们使用箭头函数的时候,箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的。
2.箭头函数中的this引用的就是最近作用域中的this
3.向外层作用域中,一层一层查找this,直到有this的定义
4.有的箭头函数都没有自己的 this。 不适合定义一个 对象的方法。
箭头函数没有自己的this指向,它会捕获自己定义所处的外层执行环境,并且继承这个this值。箭头函数的this指向在被定义的时候就确定了,之后永远都不会改变
。(!永远)
const obj = {
fun1: function () {
console.log(this);
return () => {
console.log(this);
}
},
fun2: function () {
return function () {
console.log(this);
return () => {
console.log(this);
}
}
},
fun3: () => {
console.log(this);
}
}
let f1 = obj.fun1(); // obj
f1() // obj
let f2 = obj.fun2();
let f2_2 = f2(); // window
f2_2() // window
obj.fun3(); // window
2 .apply
作用有两个,跟它的入参有关。
- 改变this指向。
- apply的第二个参数接受的是数组
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName: "张",
lastName: "三",
}
person.fullName.apply(person1); // 将返回 "张三"
console.log(person.fullName.apply(person1));
当apply调用时,调用apply的函数是谁?(person.fullName),把这个函数分享给person1,让person1去调用
3.call
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"张",
lastName: "三"
}
person.fullName.call(person1, "北京", "中国");
console.log(person.fullName.call(person1, "北京", "中国"));//张 三,北京,中国
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
4.bind
bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()中的第一个参数的值
const person = {
name: '张三',
sayHello: function(city) {
console.log(`我的名字是 ${this.name} 家在${city}`);
}
};
const person2 = {
name: '李四'
};
const sayHelloFn = person.sayHello.bind(person2,"北京");
sayHelloFn(); // 我的名字是 李四 家在北京
在上述代码中,我们定义了一个 person 对象和一个 person2 对象,两个对象都包含一个 name 属性。我们使用 bind 方法将 person 对象的 sayHello 方法绑定到 person2 对象上,创建一个新函数 sayHelloFn 。当我们调用 sayHelloFn 时,它的 this 值指向 person2 对象,因此输出结果变成了 “我的名字是 李四 家在北京.”。
除了指定 this 值外,bind 方法还可以用于柯里化函数。柯里化是一种将接受多个参数的函数转换为接受一个参数的函数的技术。例如:
function add(a, b) {
return a + b;
}
const add5 = add.bind(null, 5);
console.log(add5(3)); // Output: 8
在上述代码中,我们定义了一个 add 函数,该函数接受两个参数并返回它们的和。我们使用 bind 方法将 add 函数柯里化为一个新函数 add5,该函数接受一个参数,并将其与 5 相加。因此,当我们调用 add5(3) 时,返回值为 8。