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,["北京","中国"]));//王丽丽来自北京中国