对JavaScript中this指针的新理解分享


Posted in Javascript onJanuary 31, 2015

一直以来对this的理解只在可以用,会用,却没有去深究其本质。这次,借着《JavaScript The Good Parts》,作了一次深刻的理解。(所有调试都可以在控制台中看到,浏览器F12键)

下面我们一起来看看这个this吧。

在我们声明一个函数时,每个函数除了有定义时的parameters(形参),自身还会有额外的两个参数,一个是this,一个是arguments(实参)。arguments就是函数实际接受到的参数,是一个类数组。arguments我只做个简略的介绍,重点我们放在this指针上。

在面向对象变成中,this十分重要,它的值取决于调用的模式。而在JavaScript中,一共有4中调用模式:方法调用模式、函数调用模式、构造函数调用模式、apply调用模式。

方法调用模式

当一个函数是作为一个对象的属性时,我们通常称这个函数是这个对象的一个方法。当这个方法被调用时,this就会指向该方法所属对象。

<script type="text/javascript">

    var people = {

        name : "Yika",

        sayName : function(){

            console.log(this.name);   //"Yika"

                        //this已经绑定在了people对象上了

        }

    }

    people.sayName();

</script>

如栗子所示,this指向了sayName对象,这种通过this取得所属对象上下文的方法,就是公共方法。(publice method)

函数调用模式

当一个函数被调用时并非某个对象上的方法,那么它就是作为一个函数被调用的。

这种模式调用,this会指向window对象,即使这个函数或许是在外部函数里调用的,我们来看栗子。

<script type="text/javascript">

    var name = "window-Yika";

    var people = {

        name : "people-Yika",

        student : function(){

            console.log(this);   //这里的this绑定的是对象people

            function sayName(){

                var name = "sayName-Yika";

                console.log(this.name); //window-Yika




//即使sayName函数本身和它所在的people对象都有name值,但是this是指向window的

            };

            sayName();

        }

    }

    people.student();

</script>

这样一看,是不是大概知道该怎么解决JavaScript这个“设计错误"了呢。

是的只要在student函数里面,也就是第6行,将this缓存起来。然后再将this通过变量转移到sayName函数里就可以解决啦!

var people = {

        name : "people-Yika",

        student : function(){

            var self = this; //将this缓存起来

            function sayName(){

                var name = "sayName-Yika";

                console.log(self.name);  //"people-Yika",此时的self指向的是people对象

            };

            sayName();

        }

    }

构造函数调用模式

JavaScript里一讲到构造函数,脑海里就会有:“函数名大写!调用的时候要用new操作符!” 函数名大写好理解,是为了规范统一构造函数的命名。可是你有没有深究过为什么要用new呢?如果在一个函数前面带上new来调用,那么函数后台会创建一个指向该函数prototype的新对象,同时this也绑定在新对象上。JavaScript是一门基于原型继承的语言,对原型prototype不是很清楚的同学可以自己去查一下资料,我重点放在this上面。

我们先来看看构造函数一般长什么样子。

<script type="text/javascript">

    function People(name){

        this.name = name;    //这里的this,用new调用后便指向了新对象Yika



 this.sayName = function(){

        
console.log(this.name);  //输出

    
}

    }

var Yika = new People("Yika");  

   Yika.sayName();  //输出“Yika" ,因为Yika是通过new调用得来的,this都绑定在了Yika对象上。

</script>

乍一看,好像不是好懂,怎么刚才在函数里的this是指向window,现在不用缓存就可以指向People函数呢?

没关系,刚才不是说函数通过new调用,会在背地里自己做“做坏事”么,我们一起看看到底做了哪些事。

<script type="text/javascript">

    function People(name){

        var that = {};   //坏事一:自己生成一个对象

        that.name = name;

        that.sayName = function(){

            console.log(that.name);

        };

        return that;    //坏事二,自己会改变return的行为,return刚生成的对象

    }

    var Yika = People("Yika"); //这里可以省略new,模仿调用new操作符

    Yika.sayName(); //和刚才一样输出"Yika"

</script>

这样看就明白清楚了吧,new不仅会生成一个对象,而且还会自动return这个对象,这样自然this便指向了这个新对象。

千万记得要用 new 去调用构造函数,不然出了问题,是没有警告的,所有大写约定还是十分有必要的。

Apply调用模式

apply方法让我们构建一个参数数组传递给调用函数,也允许我们改变this值。

function.apply(this绑定的值, arguments参数数组)

apply可以说的东西太多了,我这里只举个的栗子来帮助大家理解:

<script type="text/javascript">

    function People(name){

        this.name = name;

        this.sayName = function(){

            console.log(this.name);   //sayName这个方法是属于People构造函数的

        }

    }

    function Student(name){

        People.apply(this, arguments);//借用构造函数的集成方式,就是在Student构造函数里,通过apply调用People构造函数,并改变People的this值

                                      //这样每次创建Student实例时,都会调用People构造函数

    }

    var student = new Student("Yika");

    student.sayName(); //输出“Yika”

</script>

我们可以通过apply轻易的修改函数的this绑定对象,和apply相似的方法call也有一样的效果,有兴趣的同学可以自己搜索学习一下。

好了,总算讲完改变this的四种调用模式了,方法调用模式和构造函数调用模式会用的更多,也会更重要一点,而函数调用模式,我们则要学会避开其中的陷阱。

若有错误,请及时反映,我会尽快纠正,以防误导他人,谢谢!

Javascript 相关文章推荐
window.open被浏览器拦截后的自定义提示效果代码
Nov 19 Javascript
js 获取中文拼音,Select自动匹配字母获取值的代码
Sep 23 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
Sep 16 Javascript
分享Javascript中最常用的55个经典小技巧
Nov 29 Javascript
js实现温度计时间样式代码分享
Aug 21 Javascript
基于jquery实现左右按钮点击的图片切换效果
Jan 27 Javascript
jQuery实现form表单元素序列化为json对象的方法
Dec 09 Javascript
理解js回收机制通俗易懂版
Feb 29 Javascript
JS+Canvas 实现下雨下雪效果
May 18 Javascript
AngularJs IE Compatibility 兼容老版本IE
Sep 01 Javascript
Web技术实现移动监测的介绍
Sep 18 Javascript
JavaScript实现五子棋游戏的方法详解
Jul 08 Javascript
IE下支持文本框和密码框placeholder效果的JQuery插件分享
Jan 31 #Javascript
有效提高JavaScript执行效率的几点知识
Jan 31 #Javascript
JavaScript日期时间与时间戳的转换函数分享
Jan 31 #Javascript
JavaScript监听和禁用浏览器回车事件实例
Jan 31 #Javascript
JavaScript编程中容易出BUG的几点小知识
Jan 31 #Javascript
JavaScript实现的双向跨域插件分享
Jan 31 #Javascript
JavaScript判断变量是否为空的自定义函数分享
Jan 31 #Javascript
You might like
PHP下对数组进行排序的函数
2010/08/08 PHP
php 5.3.5安装memcache注意事项小结
2011/04/12 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
网页下载文件期间如何防止用户对网页进行其他操作
2014/06/27 Javascript
JavaScript中的类与实例实现方法
2015/01/23 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
2015/04/03 Javascript
javascript实现校验文件上传控件实例
2015/04/20 Javascript
JS实现选择TextArea内文本的方法
2015/08/03 Javascript
JS实现带鼠标效果的头像及文章列表代码
2015/09/27 Javascript
浅析js中substring和substr的方法
2015/11/09 Javascript
jquery,js简单实现类似Angular.js双向绑定
2017/01/13 Javascript
基于JavaScript实现窗口拖动效果
2017/01/18 Javascript
JavaScript中的普通函数和箭头函数的区别和用法详解
2017/03/21 Javascript
javascript基于定时器实现进度条功能实例
2017/10/13 Javascript
[00:23]DOTA2群星共贺开放测试 25日无码时代来袭
2013/09/23 DOTA
Python 中的 else详解
2016/04/23 Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
2017/12/08 Python
pycharm打开命令行或Terminal的方法
2019/01/16 Python
python中利用numpy.array()实现俩个数值列表的对应相加方法
2019/08/26 Python
Django REST框架创建一个简单的Api实例讲解
2019/11/05 Python
django配置app中的静态文件步骤
2020/03/27 Python
基于nexus3配置Python仓库过程详解
2020/06/15 Python
详解Python设计模式之策略模式
2020/06/15 Python
python 模拟登陆163邮箱
2020/12/15 Python
CSS3模拟IOS滑动开关效果
2016/09/28 HTML / CSS
JAVA中运算符的分类及举例
2015/09/12 面试题
城市规划毕业生求职信
2013/10/10 职场文书
计算机应用专业应届毕业生中文求职信范文
2013/11/29 职场文书
百度吧主申请感言
2014/01/12 职场文书
2014年师德承诺书
2014/05/23 职场文书
团队激励口号
2014/06/06 职场文书
社会工作专业求职信
2014/07/15 职场文书
乡镇挂职心得体会
2014/09/04 职场文书
工作检讨书范文
2015/01/23 职场文书
2015年小学二年级班主任工作总结
2015/05/21 职场文书
庭外和解协议书
2016/03/23 职场文书