this,call(),apply()用法

this使用

在javascript中, this 不是固定不变的,它会随着执行环境的改变而改变。

  • 在方法中,this 表示该方法所属的对象。
  • 如果单独使用,this 表示全局对象。
  • 在函数中,this 表示全局对象。
  • 在函数中,在严格模式下,this 是未定义的(undefined)。
  • 在事件中,this 表示接收事件的元素。 类似 call() 和apply() 方法可以将 this 引用到任何对象。

例如,下面例子中,fullName方法中的this指向的是person对象,因为fullName 方法所属的对象就是 person:

var person = {
  firstName: "John",
  lastName : "Doe",
  id       : 5566,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

实例:

  data() {
    return {
      name: "小王",
      age: 12,
    };
  },
  methods: {
    myFun() {
      var obj = {
        name: "小张",
        objAge: this.age,
        objFun: function () {
          console.log(this.name + this.age);//使用function时,方法里面调用的this指向它的父级obj,但是obj对象中没有age属性,所有this.age结果是undefined,如果把function改成箭头函数()=>{}就可以拿到this.age
        },
      };
      console.log(obj.objAge);//输出结果12
      obj.objFun();//输出结果:小张,undefined
    },
  },

分析,上述例子中拿不到this.age,是因为使用function里面的this指向的是obj,但是obj里面没有age属性,所以返回undefined。改成箭头函数如下:

objFun: ()=> {
          console.log(this.name , this.age);//输出结果:小张 12
 },

上面问题使用call()和apply()方法解决this指向:

  data() {
    return {
      name: "小王",
      age: 12,
    };
  },
  methods: {
    myFun() {
      var obj = {
        name: "小张",
        objAge: this.age,
        objFun: function(){
          console.log(this.name,this.age)
        }
      };
      var obj2={
        name:"丽丽",
        age:16
      };
      obj.objFun.call(obj2);//丽丽 16
      obj.objFun.apply(obj2);//丽丽 16
    },
  },

call()方法和apply()方法

主要作用:修改函数中this的指向。

在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。

在下面实例中,当我们使用 person2 作为参数来调用 person1.fullName 方法时, this 将指向 person2, 即便它是 person1 的方法:
实例:

var person1 = {
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
}
var person2 = {
  firstName:"John",
  lastName: "Doe",
}
person1.fullName.call(person2);  // 返回 "John Doe"

作用:每个函数都包含两个非继承而来的方法:call()方法和apply()方法。这两个方法的作用是一样的。都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。

一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。

apply()和call差不多,只不过apply第二个参数必须传入的是一个数组,而call 第二个参数可以是任意类型。

语法:
A.call(B,x,y)

  • 改变函数A的this指向,使之指向B; 2
  • 把A函数放到B中运行,x和y是A函数的参数。

call()

用 call() 方法,您可以编写能够在不同对象上使用的方法。
使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。注意:该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。
描述:
允许为不同的对象分配和调用属于一个对象的函数/方法。提供新的this值给当前调用的函数/方法。你可以使用call来实现继承,写一个方法,然后让另一个新对象来继承它。

语法

function.call(thisArg,arg1,arg2,...)

参数说明:
thisArg可选:
在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
arg1,arg2…
指定的参数列表。

返回值:
使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。

如下实例,使用call()方法调用父构造函数。

在一个子构造函数中,你可以通过调用父构造函数的 call 方法来实现继承,类似于 Java 中的写法。下例中,使用 Food 和 Toy 构造函数创建的对象实例都会拥有在 Product 构造函数中添加的 name 属性和 price 属性,但 category 属性是在各自的构造函数中定义的。

// 定义一个构造函数Product
function Product(name, price) {
  this.name = name;
  this.price = price;
}
// 定义一个构造函数Food
function Food(m, n) {
  // 调用Product构造函数,此刻它就拥有Product中的name和price属性
  Product.call(this, m, n);
  //可以自己创建属于自己的属性category
  this.category = 'food';
}
// 定义一个构造函数Toy
function Toy(x, y) {
  //调用Product构造函数,拥有name和price属性
  Product.call(this, x, y);
  //创建自己的属性category
  this.category = 'toy';
}
var cheese = new Food('feta', 5);//实例化对象
console.log(cheese);//Food {name: "feta", price: 5, category: "food"}
var fun = new Toy('robot', 6);//实例化对象
console.log(fun);//Toy {name: "robot", price: 6, category: "toy"}

实例,使用call()方法调用匿名函数

在下例中的 for 循环体内,我们创建了一个匿名函数,然后通过调用该函数的 call 方法,将每个数组元素作为指定的 this 值执行了那个匿名函数。这个匿名函数的主要目的是给每个数组元素对象添加一个 print 方法,这个 print 方法可以打印出各元素在数组中的正确索引号。当然,这里不是必须得让数组元素作为 this 值传入那个匿名函数(普通参数就可以),目的是为了演示 call 的用法。

var animals=[{spe:'dog',name:'jack'},{spe:'cat',name:'coco'}];
for(var i=0;i<animals.length;i++)
{
  (function(i){this.print=function(){
    console.log(i+this.spe+this.name);
  }
  this.print();
  }).call(animals[i],i);
}
//0 dog jack
//1 cat coco

实例,使用 call 方法调用函数并且指定上下文的 ‘this’

function greet(){
  var reply=[this.animal,this.sleep].join(',');
  console.log(reply);
}
var obj={
  animal:'cat',sleep:'12h'
};
greet.call(obj);//cat,12h

实例,使用call(),apply(),bind()来重新定义this的指向。

var name="小王";
var age=12;
var obj={
  name:'小青',
  objAge:this.age,
  myFun:function(){
    console.log(this.name,this.age)
  }
}
 var db={
   name:'小丽',
   age:14
 }
 obj.myFun.call(db);//小丽 14
 obj.myFun.apply(db);//小丽 14

以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行。

实例,对比call,bind,apply传参情况

var name="小王";
var age=16;
var obj={
  name:'小张',
  objAge:this.age,
  myFun:function(x,y)
  {
    console.log(`姓名:${this.name},年龄${this.age},从${x},飞到${y}`);
  }
}
var db={
  name:'jack',
  age:20
}
obj.myFun.call(db,'成都','上海');//姓名:jack,年龄20,从成都,飞到上海
obj.myFun.apply(db,['北京','广州']);//姓名:jack,年龄20,从北京,飞到广州
obj.myFun.bind(db,'成都','上海')();//姓名:jack,年龄20,从成都,飞到上海
obj.myFun.bind(db,['成都','上海'])();//姓名:jack,年龄20,从成都,上海,飞到undefined

从上面四个结果不难看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,‘成都’, … ,‘string’ )。
apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,[‘成都’, …, ‘string’ ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

实例,call可以用来调用所有者对象作为参数的方法。通过 call(),您能够使用属于另一个对象的方法。

var person={
  fullName:function(){
    return this.firstName+this.lastName;
  }
}
var p1={
  firstName:'Bill',
  lastName:'Gate'
}
var p2={
  firstName:'Jack',
  lastName:'Jobs'
}
console.log(person.fullName.call(p1));//BillGate
console.log(person.fullName.call(p2));//JackJobs

实例

//父类Person
function Person() {
  this.sayName = function () {
    return this.name;
  }
}
//子类china
function china(x) {
  Person.call(this);//借助call()方法实现继承,china继承了Person方法中的属性
  this.name = x;
  this.ch = function () {
    console.log("我是中国馆人")
  }
}
//实例化china方法
var c = new china('李小龙');
//  调用父类的方法
console.log(c.sayName());//李小龙

call() 和 apply() 之间的区别

不同之处是:
call() 方法分别接受参数。
apply() 方法接受数组形式的参数。
如果要使用数组而不是参数列表,则 apply() 方法非常方便。

实例,apply()

var person={
  fullName:function(){
    return this.firstName+this.lastName;
  }
}
var p1={
  firstName:"王",
  lastName:"丽丽"
}
console.log(person.fullName.apply(p1));//王丽丽
var person={
  fullName:function(city,contry){
    return this.firstName+this.lastName+"来自"+city+contry;
  }
}
var p1={
  firstName:"王",
  lastName:"丽丽"
}
console.log(person.fullName.apply(p1,["北京","中国"]));//王丽丽来自北京中国
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值