构造函数中中this重写函数方法

来源:互联网 发布:java ssh书籍推荐 编辑:程序博客网 时间:2024/06/03 19:58

原文地址:http://www.zhangyunling.com/?p=293


这篇文章,说起来也没有什么要表达的东西,只是想要说明一点,就算是我们很熟知的知识点,如果你平时不使用,那么关于这个知识点,你也只能算是懂而已,并不代表你会,尤其是,当你在使用时,所以,多实践,才是学习掌握一门技术的不二之选。

概述

构造函数有一个知识点,如果你对构造函数有了解,那么就必定会知道这个知识点,那就是,实例中定义的属性,会覆盖原型链的属性。

开始

首先看下面这个例子,相信只要你对构造函数的实例化有一些了解,那么你就应该对下面这个实例,有一个很明确的认识:

<span style="font-size:14px;">function Person(name){  this.name = name;}Person.prototype.getName = function(){  return this.name;};var per = new Person("zhang");console.log(per.getName());   //?per.getName = function(){  return "ling";};console.log(per.getName());   //?delete per.getName;console.log(per.getName());   //?</span>


没有什么问题,这就是正常的表现。

但是,游戏饿时候,我希望原型链中的函数,只执行一次,而不是像上面那么,显示的去定义一个同名的属性或者方法,把原型链中的覆盖掉。

而且,有一个问题就是,难道在每次实例化时,还得多加上N多代码,把不想要的原型链上的方法,都给覆盖掉,想想就有些扯淡,这个时候,就要想想了,原型链方法中,我们习惯使用的this关键字,是指向哪里的?

在构造函数的实例化时,this关键字,总是指向实例化时新生成的那个对象。

比如前面代码,在实例化Person时,在原型链方法中的this就是作为返回值赋值给了per变量,所以,per === this;

其实,这和我之前关于this的介绍也是相同的理解,想想原型链中的this是在什么时候被调用呢,只有在该方法被调用的时候,才会把this的指向给赋值。

所以,对上面的代码,进行一点点更改:

<span style="font-size:14px;">function Person(name){this.name = name;}Person.prototype.getName = function(){if(this === window){console.log("this === window");}else if(this === per){console.log("this === per");}else {console.log(this);}return this.name;};var per = new Person("zhang");per.getName();   //?var getName = per.getName;getName();    //?</span>


关于上面为什么会有这些,不了解或者感到迷惑的,请参考:函数中this的指向-简单认识,关于闭包的一些-胡思乱想。

OK,刚才算是一个小的插曲,现在继续,既然this是指向实例化后的对象的,那么如果我在调用到该函数一次之后,重写该方法,是不是就可以实现了一些原型链中的方法,只调用一次的问题?

所以,继续更改原来的代码:

<span style="font-size:14px;">function Person(name){this.name = name;}Person.prototype.getName = function(){this.getName = null;return this.name;};var per = new Person("zhang");console.log(per.getName());   //?//下面的代码,就是确认下,执行一次getName之后,是否还有getName的值if(typeof per.getName == "function"){console.log("if 1");console.log(per.getName());//?}else{console.log("else 1");console.log(per.getName);}</span>

上述代码,也就证明了前面说的方法是可行的,我们可以在原型链中的方法内部,直接限制该方法,在是实例化之后,只运行一次的问题。

那么问题就来了,如果我在原型链中的方法内部,把本方法重写,会不会影响下次实例化时,调用该方法呢?那么你就需要了解到一个问题了,原型链中的this的指向问题?关于这一点,本文前面有之处,如果您到这里还有这个疑问,请向前翻看本文。

并且,为了能更好的理解这个问题,那么下面进行一些测试:

function Person(name){this.name = name;}Person.prototype.getName = function(){this.getName = null;return this.name;};var per = new Person("zhang"),per2 = new Person("ling");console.log(per.getName());  //?console.log(per2.getName()); //?if(typeof per.getName == "function"){console.log("if 1");console.log(per.getName());//?}else{console.log("else 1");console.log(per.getName);}delete per.getName;if(typeof per.getName == "function"){console.log("if 2");console.log(per.getName());//?}else{console.log("else 2");console.log(per.getName);}


这证明了两个问题:
1:原型链中,使用this.getName重写getName的方法,并不会影响到其他实例化时,对getName的调用。
2:在原型链中的方法中,使用this.getName=null重新赋值,只是改变了实例化之后的实例的getName方法,而对于构造函数Person的原型链中的getName的方法,是没有影响的,只是把原型链中的getName的方法给覆盖了而已。所以,使用delete方法,删除实例中的getName之后,依然可以访问原型链中的getName方法。

因为通过delete方法删除实例中的同名方法,还是可以继续访问原型链中的属性和方法的,所以,该方法只能算是取巧,也算是对this和构造函数的进一步理解吧。


0 0
原创粉丝点击