美文网首页
【Javascript】this

【Javascript】this

作者: 嘻洋洋 | 来源:发表于2018-09-25 17:00 被阅读0次

this的含义

this 本身原本很简单,总是指向类的当前实例。因此编写的 JS 采用函数式写法,而不是面向对象式,你所有的代码里 this 会少很多,甚至没有。所以应用场景就是用 this 时,应该是在使用对象/类 方式开发,否则 this 只是函数调用时的副作用。

this的约定

  • 在 function 内部被创建
  • 指向调用时所在函数所绑定的对象
  • this 不能被赋值,但可以被 call/apply 改变

this的常见应用场景

this 和构造器

this 本身就是类定义时构造器里需要用到的,按照 JavaScript 的习惯写法, this 应该挂属性/字段,方法都应该放在原型上。

function Tab(nav, content) {
    this.nav = nav
    this.content = content
}
Tab.prototype.getNav = function() {
    return this.nav;
};

this 和对象

JS 中的对象不用类也可以创建,当我们用 OOP 方式写 JS 代码,可避免的会用到 this,方法内会访问类的内部属性(字段),也可能会调用类的另一个方法

var tab = {
    nav: '',
    content: '',
    getNav: function() {
        return this.nav;
    },
    setNav: function(n) {
        this.nav = n;
    }
}

当类的方法内又有一个 function 时,比如浏览器端开发经常遇见的给 DOM 元素添加事件,这时如果事件处理器(handler)中的想调用类的一个方法,此时 handler 内的 this 是 dom 元素而非类的当前对象。这个时候,需要把 this 暂存,开发者发挥着自己的聪明才智留下了几种经典的命名 me, self, that, _this。

function listenEvents(){
    
    $(".my_foot_today ul li").on("mouseover ",function(){
        $(this).find('.foot_chacha').stop().fadeIn(100);
    }).on("mouseout",function(){
        $(this).find('.foot_chacha').stop().fadeOut(100);
    })
    $(".del_today a").on("click",function(){
        var _this_ = $(this);
        ConfirmBox.confirm("", "确认删除当天的浏览记录吗?", function(){
            var date = _this_.data("date");
            var goodsList = [];
            $(".my_foot_today[data-date='" + date + "'] li").each(function(){
                goodsList.push(parseInt($(this).data("goodsid")));
            });
            delHistory(goodsList,date);
            return true;
        },function(){
            return true;
        }) 
    })
}

this 和函数

this 和独立的函数放在一起是没有意义的。

function showMsg() {
    alert(this.message)
}
showMsg() // undefined

定义 showMsg,然后以函数方式调用(函数所绑定的对象就是window),因此这里的this是window对象,this.message 是 undefined。因此坚决杜绝在 纯函数内使用 this,但有时候会这么写,调用方式使用 call/apply。

function showMsg() {
    alert(this.message)
}
var m1 = {
    message: '输入的电话号码不正确'
}
var m2 = {
    message: '输入的身份证号不正确'
}
showMsg.call(m1) // '输入的电话号码不正确'
showMsg.call(m2) // '输入的身份证号不正确'

用这种方式可以节省一些代码量,比如当两个 类/对象 有一共相似的方法时,不必写两份,只要定义一个,然后将其绑定在各自的原型和对象(作为this参数绑定进来)上。这时候其实你还是在函数里面使用对象或类(),只是间接使用罢了。关于call/apply用法查看另外我的另外一篇。

全局环境的 this

this 是 “指向调用时所在函数所绑定的对象”,这句话没毛病,有时候我们也会在全局环境中使用(很少使用),全局环境中有不同的宿主对象,浏览器环境中是 window, node 环境中是 global。
浏览器环境中非函数内 this 指向 window。

alert(window=== this) // true

因此你会看很很多开源 JS lib 这么写,比如jQuery,requirejs,:

(function() {
    // ...
})(this);
(function() {
    // ...
}).call(this);
(function() {
    // ...
})(window);

把全局变量 window 传入匿名函数。

this 和 DOM/事件

this指向div,button等DOM对象

<!-- this 指向 div -->
<div onclick="alert(this)"></div>

$('#nav').on('click', function() {
    alert(this) // 指向 nav
})

this和call/apply

call/apply 是函数调用的另外两种方式,两者的第一个参数都可以改变函数的上下文 this。具体参照上面的。
call/apply 在 JS 里体现动态语言特性及动态语言的流行原因,其在 JS 用途如此广泛。ES5发布时将其采纳,提了一个更高级的方法 bind

var modal = {
    message: 'This is A'
}
function showMsg() {
    alert(this.message)
}
var otherShowMsg = showMsg.bind(modal)
otherShowMsg()

ES6 箭头函数(arrow function) 和 this

判断 this 指向谁,看执行时而非定义时,只要函数(function)没有绑定在对象上调用,它的 this 就是 window。 ,前面一直用这句话来判断 this 的指向,在箭头函数里前面半句就失效了,箭头函数的特征就是,定义在哪,this 就指向那。即箭头函数定义在一个对象里,那箭头函数里的 this 就指向该对象。

var book = {
    author: 'John Resig',
    init:  function() {
        document.onclick = ev => {
            alert(this.author) ; // 这里的 this 不是 document 了
        }
    }
};
book.init()

对象 book 里有一个属性 author, 有一个 init 方法, 给 document 添加了一个点击事件,如果是传统的函数,我们知道 this 指向应该是 document,但箭头函数会指向当前对象 book。

总结

this 本质是和面向对象联系的,和写类,对象关联一起的, 和“函数式”没有关系的。如果你采用过程式函数式开发,完全不会用到一个 this。

相关文章

网友评论

      本文标题:【Javascript】this

      本文链接:https://www.haomeiwen.com/subject/azbnnftx.html