this指向问题
自己实现一个 bind 函数
原理:通过 apply 或者 call 方法来实现。 1 初始版本
Function.prototype.bind=function(obj,arg){
var arg=Array.prototype.slice.call(arguments,1);
var context=this;
return function(newArg){
arg=arg.concat(Array.prototype.slice.call(newArg));
return context.apply(obj,arg);
}}
2 考虑到原型链 为什么要考虑?因为在 new 一个 bind 过生成的新函数的时候,必须的条件是要继承原 函数的原型
Function.prototype.bind=function(obj,arg){
var arg=Array.prototype.slice.call(arguments,1);
var context=this;
var bound=function(newArg){
arg=arg.concat(Array.prototype.slice.call(newArg));
return context.apply(obj,arg);
}
var F=function(){}
//这里需要一个寄生组合继承
F.prototype=context.prototype;
bound.prototype=new F();
return bound;
}
this的指向哪几种
默认绑定:全局环境中,this 默认绑定到 window。
隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,this 隐式绑定到该直接对象。
隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到 window。
显式绑定:通过 call()、apply()、bind()方法把对象绑定到 this 上,叫做显式绑定。
new 绑定:如果函数或者方法调用之前带有关键字 new,它就构成构造函数调用。对于this 绑定来说,称为 new 绑定。
【1】构造函数通常不使用 return 关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。
【2】如果构造函数使用 return 语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果。
【3】如果构造函数显式地使用 return 语句返回一个对象,那么调用表达式的值就是这个对象。
箭头函数的 this 指向哪⾥?
箭头函数的 this 指向是在函数定义时确定的,并且在整个函数生命周期内保持不变。与常规函数(函数声明或函数表达式)不同,箭头函数没有自己的 this 绑定。相反,它继承了父作用域中的 this 值。
具体来说,箭头函数的 this 指向的是其外部包围函数(或全局作用域)的 this 值。这意味着,无论如何调用箭头函数,它始终引用的是最近一层非箭头函数作用域的 this 值。
考虑以下示例:
function regularFunction() {
console.log(this); // this 指向调用 regularFunction 的对象
}
const arrowFunction = () => {
console.log(this); // this 指向外部作用域中的 this 值
};
const obj = {
method: regularFunction,
};
regularFunction(); // this 指向全局对象(浏览器环境中通常是 window)
obj.method(); // this 指向 obj 对象
arrowFunction(); // this 指向外部作用域中的 this 值(在此处通常是全局对象)
在上述示例中,regularFunction 是一个常规函数,它的 this 值取决于调用它的方式,可以通过 obj.method() 来改变其 this 指向。而 arrowFunction 是一个箭头函数,它的 this 始终继承自外部作用域,无法通过调用方式改变其 this 指向。
需要注意的是,箭头函数不适合作为构造函数使用,因为它没有自己的 this 绑定,无法通过 new 关键字来实例化。
改变函数内部 this 指针的指向函数(bind,apply,call 的区别)
通过 apply 和 call 改变函数的 this 指向,他们两个函数的第一个参数都是一样的表 示要改变指向的那个对象,第二个参数,apply 是数组,而 call 则是 arg1,arg2...这 种形式。通过 bind 改变 this 作用域会返回一个新的函数,这个函数不会马上执行。
对this对象的理解
this 是 JavaScript 中的特殊对象,它代表当前执行上下文中的对象或者说是当前执行代码所属的对象。this 的值在函数执行时动态绑定,取决于函数的调用方式。
下面是对 this 的一些常见情况和使用场景的解释:
-
全局作用域中的
this:- 在全局作用域中,函数没有明确的调用对象,此时
this指向全局对象(在浏览器中为window对象)。 - 在严格模式下,全局作用域中的
this值为undefined。
- 在全局作用域中,函数没有明确的调用对象,此时
-
函数作为对象的方法调用时的
this:- 当函数作为对象的方法被调用时,
this指向调用该方法的对象。 - 方法中的
this可以用于引用该对象的属性和方法。
- 当函数作为对象的方法被调用时,
-
函数使用
call()、apply()或bind()显式指定this:- 使用
call()或apply()方法可以显式指定函数执行时的this值。 call()方法接受多个参数,第一个参数指定this的值,后续参数为函数的参数。apply()方法接受两个参数,第一个参数指定this的值,第二个参数为一个 数组,包含了函数的参数。bind()方法返回一个新函数,并预先指定this值。调用新函数时,this将始终保持预先指定的值。
- 使用
-
构造函数中的
this:- 当函数作为构造函数使用时(使用
new关键字),this指向新创建的实例对象。 - 在构造函数中,可以使用
this来设置实例对象的属性和方法。
- 当函数作为构造函数使用时(使用
-
箭头函数中的
this:- 箭头函数的
this值继承自外层的作用域,与普通函数不同,箭头函数没有自己的this。 - 在箭头函数中使用的
this实际上是定义时所在作用域中的this。
- 箭头函数的
注意:this 的值是在函数被调用时确定的,并且与函数的定义位置无关。所以在编写代码时,需要根据具体情况正确理解和使用 this。
call() 和 apply() 的区别?
call() 和 apply() 是 JavaScript 中函数对象的两个方法,用于显式调用函数并指定函数执行时的 this 值。它们的区别在于参数的传递方式。
区别如下:
-
参数传递方式:
call()方法使用参数列表的方式传递参数,即将参数按照逗号分隔的形式依次传递给函数。apply()方法使用数组的方式传递参数,即将参数封装在数组中作为单个参数传递给函数。
-
参数数量:
call()方法可以接受任意数量的参数,第一个参数是要指定的this值,后续参数是函数的参数。apply()方法只接受两个参数,第一个参数是要指定的this值,第二个参数是一个数组,包含了函数的参数。
示例代码如下:
function greet(message) {
console.log(message + ', ' + this.name);
}
const person = {
name: 'John',
};
// 使用 call() 方法调用 greet() 函数,并指定 this 为 person 对象
greet.call(person, 'Hello'); // 输出: Hello, John
// 使用 apply() 方法调用 greet() 函数,并指定 this 为 person 对象,参数以数组形式传递
greet.apply(person, ['Hi']); // 输出: Hi, John
在上述代码中,greet 函数使用 call() 和 apply() 方法分别调用,并指定了 this 值为 person 对象。通过传递不同的参数,可以实现对函数的显式调用并设置函数执行时的 this 值和参数。
总结:call() 和 apply() 方法的区别主要在于参数传递方式的不同,call() 使用参数列表传递参数,而 apply() 使用数组传递参数。根据具体的需求和参数的形式,选择合适的方法来调用函数。