对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 相关文章推荐
Javascript 类型转换方法
Oct 24 Javascript
在JQuery dialog里的服务器控件 事件失效问题
Dec 08 Javascript
jQuery学习笔记(4)--Jquery中获取table中某列值的具体思路
Apr 10 Javascript
扩展js对象数组的OrderByAsc和OrderByDesc方法实现思路
May 17 Javascript
js实现点击图片将图片地址复制到粘贴板的方法
Feb 16 Javascript
vue双向绑定的简单实现
Dec 22 Javascript
微信小程序 自定义对话框实例详解
Jan 20 Javascript
AngularJS Toaster使用详解
Feb 24 Javascript
自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结
Aug 18 Javascript
为输入框加入数字js校验代码分享
Nov 02 Javascript
详解Vue SPA项目优化小记
Jul 03 Javascript
JavaScript代理模式原理与用法实例详解
Mar 10 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
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
PHP实现给定一列字符,生成指定长度的所有可能组合示例
2019/06/22 PHP
javascript[js]获取url参数的代码
2007/10/17 Javascript
初学Jquery插件制作 在SageCRM的查询屏幕隐藏部分行的功能
2011/12/26 Javascript
js判断undefined类型,undefined,null, 的区别详细解析
2013/12/16 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
node.js下LDAP查询实例分享
2015/09/30 Javascript
js获取本机操作系统类型的两种方法
2015/12/19 Javascript
jQuery实现背景弹性滚动的导航效果
2016/06/01 Javascript
JavaScript表单验证开发
2016/11/23 Javascript
JS获取本周周一,周末及获取任意时间的周一周末功能示例
2017/02/09 Javascript
微信小程序 template模板详解及实例
2017/02/21 Javascript
jQuery实现ajax无刷新分页页码控件
2017/02/28 Javascript
node.js实现微信JS-API封装接口的示例代码
2017/09/06 Javascript
nodejs微信开发之授权登录+获取用户信息
2019/03/17 NodeJs
[50:58]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 Mineski vs EG
2018/04/03 DOTA
python实现问号表达式(?)的方法
2013/11/27 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
python+opencv实现动态物体识别
2018/01/09 Python
python互斥锁、加锁、同步机制、异步通信知识总结
2018/02/11 Python
对Python 除法负数取商的取整方式详解
2018/12/12 Python
Django中的session用法详解
2020/03/09 Python
pycharm 复制代码出现空格的解决方式
2021/01/15 Python
CSS3系列教程:背景图片(背景大小和多背景图) 应用说明
2012/12/19 HTML / CSS
CSS3绘制超炫的上下起伏波动进度加载动画
2016/04/21 HTML / CSS
HTML5中新标签和常用标签详解
2014/03/07 HTML / CSS
Canvas图片分割效果的实现
2019/07/29 HTML / CSS
波兰最大的宠物用品网上商店:FERA.PL
2019/08/11 全球购物
介绍一下Linux内核的排队自旋锁
2014/01/04 面试题
财务担保书范文
2014/04/02 职场文书
大学生作弊检讨书
2014/09/11 职场文书
餐饮店长岗位职责
2015/04/14 职场文书
2015年保险公司个人工作总结
2015/05/22 职场文书
如何写好一份优秀的工作总结?
2019/06/21 职场文书
初中运动会闭幕词范本3篇
2019/12/09 职场文书
Java实现给Word文件添加文字水印
2022/02/15 Java/Android