欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 如何灵活运用JavaScript中的this

程序员文章站 2022-03-22 10:05:25
JavaScript中的this面对对象的语言中,this表示当前对象的一个引用,但在JavaScript中,this不是固定不变的,它会随之执行环境的改变而改变。一般情况下this指向全局变量window作为对象方法调用时,this指向上级对象作为构造函数调用时,this指向new出的对象在函数中,非严格模式下this指向全局对象,但是在严格模式下this指向undefined[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LwMy7ONK-15946141...

JavaScript中的this

面对对象的语言中,this表示当前对象的一个引用,但在JavaScript中,this不是固定不变的,它会随之执行环境的改变而改变。

一般情况下this指向全局变量window
荐
                                                        如何灵活运用JavaScript中的this

作为对象方法调用时,this指向上级对象
荐
                                                        如何灵活运用JavaScript中的this

作为构造函数调用时,this指向new出的对象

荐
                                                        如何灵活运用JavaScript中的this

在函数中,非严格模式下this指向全局对象,但是在严格模式下this指向undefined

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LwMy7ONK-1594614184278)(荐
                                                        如何灵活运用JavaScript中的this])

在事件中,this表示接收事件的元素
荐
                                                        如何灵活运用JavaScript中的this

欢迎访问我的网站: www.dengzhanyong.com

改变this的指向

在JavaScript中,我们可以通过callapplybind来改变this的指向,以满足不同的场景需求。

举个栗子

var apple = {
  name: '苹果',
  color: '红色',
  fn: function(){
    console.log(`${this.name}${this.color}的`)
   }
 }
apple.fn()   //苹果是红色的

有一个apple对象,它有namecolor两个属性,还有一个方法fn用来打印出name和color。

如果现在有一个新的对象banana

var banana = {
  name: '香蕉',
  color: '黄色'
}

现在我也想打印出banana的信息,但是我并不想再写一遍fn方法,如果可以直接利用apple的fn方法那就简化了很多。

apple.fn.call(banana)   //香蕉是黄色的

通过call方法可以改变apple.fn中this的指向,指向的对象为接受的第一个参数。我们还可以在后面传入多个参数,就像下面这样:

var apple = {
  name: '苹果',
  color: '红色',
  fn: function(price, unit){
    console.log(`${this.name}${this.color}的,${price}元/${unit}`)
  }
}

apple.fn.call(banana, 3.99, '斤') //香蕉是黄色的,3.99元/斤

apply与call的用法几乎相同,唯一的区别就是传入参数不同,第一个参数同样是目标对象,剩余的参数以一个数组的形式传入,如下:

apple.fn.apply(banana, [3.99, '斤']) //香蕉是黄色的,3.99元/斤

bind的作用也是改变this的指向,但它与callapply不同的是,它会返回一个函数,而不是立即执行,传参方式与call相同。

var fn2 = apple.fn.bind(banana, 3.99, '斤')
fn2() //香蕉是黄色的,3.99元/斤

当第一个参数为nullundefinedNaN空字符串时,默认传入全局对象

如果第一个参数为numberboolean类型的值时,会自动将其转为对应的包装对象。

常见应用场景

查找数组最大元素

var a = [3, 9, 5, 3, 6]
console.log(Math.max.apply(null, a))   //9
console.log(Math.max.apply(undefined, a))   //9
console.log(Math.max.apply(NaN, a))   //9
console.log(Math.max.apply('', a))   //9
console.log(Math.max.call(null, ...a))   //9

将数组的空元素变为undefined

var b = [3, ,8 , , 4, 7]
console.log(Array.apply(null, b))   //[3, undefined, 8, undefined, 4, 7]
console.log(Array.call(null, ...b))   //[3, undefined, 8, undefined, 4, 7]

调用对象的原生方法

Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。如果某个对象中重写了hasOwnProperty方法,那我们再使用hasOwnProperty()是无法得到正确的结果的。

var obj = {}
console.log(obj.hasOwnProperty('name'))   //false
obj.hasOwnProperty = function(){
return true
}
console.log(obj.hasOwnProperty('name'))   //true
console.log(Object.prototype.hasOwnProperty.call(obj, 'name'))   //false

在上面的代码中,在obj对象中使用原生的Object.prototype.hasOwnProperty方法可以避开使用被覆盖的hasOwnProperty

对于许多原生的方法,我们都可以使用call、apply、bind来得到同样的结果,他们是等价的,就像下面这样:

[1, 2, 3].slice(0, 1)  //[1]
Array.prototype.slice.call([1, 2, 3], 0, 1)    //[1]

使用ES6手写call、apply、bind

function add(c, d) {
return this.a + this.b + c + d;
}
const obj = { a: 1, b: 2 };
// ES6 call 实现
Function.prototype.es6call = function (context, ...rest) {
  var context = context || window;
  context.fn = this;
  const result = context.fn(...rest);
  delete context.fn;
  return result;
}
console.log(add.es6call(obj, 3, 4));  //10
  • context 代表接收的上下文环境,…rest接收的其他参数
  • 若context 为空值,则默认为window
  • 将被调用对赋值给context.fn,此时context.fn中可以访问到context中的其他属性,context.fn中的this不再指向它的原对象,而是新的对象context。

context.fn(…rest)将其他的参数传入函数中执行得到结果

Function.prototype.es6apply = function(context, arr){
  var context = context || window
  context.fn = this
  const result =  context.fn(...arr)
  delete context.fn
  return result
}
​
console.log(add.es6apply(obj, [3, 4]));  //10

apply的实现与call的实现几乎相同,唯一区别就是接受参数的形式不同,一个是多个参数形式,一个是把多个参数转为一个数组的形式。


Function.prototype.es6bind = function(context, ...rest) {
  var self = this;
  return function fn(...args) {
  var result =  this instanceof fn ? new self(...rest, ...args) : self.apply(context, rest.concat(args))
    return result
  }
}

bind接受参数与call相同,返回结果为一个函数

我的网站:www.dengzhanyong.com

关注我的公众号,不错过每一篇推送

荐
                                                        如何灵活运用JavaScript中的this

本文地址:https://blog.csdn.net/DengZY926/article/details/107315133