this指向
哪个对象调用函数,函数里面的this指向哪个对象。
let name = ‘tom‘
function a(){
let name = ‘jerry‘;
console.log(this.name)
}
let obj = {
name: ‘mark‘,
fun: function(){
let name = ‘james‘
console.log(this.name)
}
}
// 调用
a() // window.a() undefined
obj.fun() // obj.fun() mark
/**
* this.name 是某个对象中的 name 属性,而不是函数中的变量 name,注意区分
**/
稍微特殊一点的,但还是可以用上面那一句话解释
let obj1={
name: "tom"
}
let obj2={
name: "jerry",
fun:function(){
console.log(this.name);
}
}
obj1.fun = obj2.fun;
obj1.fun(); //111
/***
上面的赋值就等价:
let obj1={
name: "tom",
fun:function(){
console.log(this.name);
}
}
***/
构造函数
function Person(){
this.name = ‘person‘
}
let person = new Person()
let tom = new Person()
tom.name = ‘tom‘
let jerry = new Person()
jerry.name = ‘jerry‘
console.log(tom.name) // tom
console.log(jerry.name) // jerry
console.log(person.name) // person
箭头函数和普通函数的区别如下:
普通函数:根据调用我的人(谁调用我,我的this就指向谁)
箭头函数:根据所在的环境(我再哪个环境中,this就指向谁)
实现apply, call, bind函数
call 实现
Function.prototype.myCall = function(context){
// 保存传进来的参数
context = context || window;
// 保存调用函数本身的属性和方法
context.invokeFun = this;
// 获取传进来对象的属性和方法
let args = [...arguments].slice(1);
// 将两个保存再一起
let result = context.invokeFun(...args);
// 删除防止污染作用域
delete context.invokeFun;
// 现在这个result我理解为 a.call(b) ,是a, b两个的集合,返回这个集合
return result;
}
let obj = {
name: ‘tom‘,
age: 22,
fun: function(){
console.log(‘我是object中的函数‘);
}
}
function my(){
this.gender = ‘male‘;
console.log(this.name+‘,‘+this.age+","+this.gender);
this.fun();
}
my.myCall(obj);
/**
* 输出: tom,22,male
* 我是object中的函数
**/
my();
/**
* 输出: undefined,undefined,male
* Uncaught TypeError: this.fun is not a function
**/
我的理解就是将两个对象的属性和方法保存再一个对象中然后再返回。
在补充一下arguments是将函数传入的参数以类似数组的形式保存。
function foo(a, b, c){
let name = a;
let age = b;
let gender = c;
console.log(arguments);
}
foo(‘tom‘, 12, ‘male‘);
// 输出: [‘tom‘, 12, ‘male‘]
欢迎指正,嘿嘿嘿^ ^。
** apply 实现 **
call 和 apply 一样,只是参数不同
Function.prototype.myApply = function(context){
// 保存传进来的参数
context = context || window;
// 保存调用函数本身的属性和方法
context.invokeFun = this;
// 获取传进来对象的属性和方法
let result;
if(arguments[1]){
result = context.invokeFun(...arguments[1])
}else{
result = context.invokeFun()
}
// 删除防止污染作用域
delete context.invokeFun;
// 现在这个result我理解为 a.call(b) ,是a, b两个的集合,返回这个集合
return result;
}
let obj = {
name: ‘tom‘,
age: 22,
fun: function(){
console.log(‘我是object中的函数‘);
}
}
function my(){
this.gender = ‘male‘;
console.log(this.name+‘,‘+this.age+","+this.gender);
this.fun();
}
my.myApply(obj);
/**
* 输出: tom,22,male
* 我是object中的函数
**/
my();
/**
* 输出: undefined,undefined,male
* Uncaught TypeError: this.fun is not a function
**/
bind 实现
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值。
当使用new 操作符调用绑定函数时,该参数无效。
Function.prototype.myBind = function(context){
// 获取除了一个参数以外的所有参数
let args = [...arguments].slice(1);
// 定义一个函数,用于下面判断是否使用 new 操作符绑定该函数
F = function(){};
// 此处的 this 指调用函数,即 a.bind(obj) 中的 a
self = this;
// 因为 bind 被调用时并不是立即执行
// 而是创建一个新函数
// 当新函数被执行时, 用 call 就可以了
bound = function(){
let finalArgs = [...args, ...arguments];
// 下面的 this 是指用 new 实例化出的对象
return self.call((this instanceof F ? this:context), finalArgs)
}
F.prototype = self.prototype;
bound.prototype = new F()
return bound;
}
function my(){
console.log(this.name);
}
let obj = {
name: ‘rbt‘
}
let temp = my.myBind(obj);
temp() // rbt