在Javascript面向对象编程中经常需要使用到this,prototype和constructor这3个关键字.

1.首先介绍一下this的使用:this表示当前对象;如果在全局中使用this,则this为当前页面对象window;如果在函数中使用this,则this为调用该函数的对象;可以使用apply和call两个全局函数来改变this的指向。

接下来,首先通过几个demo程序验证一下:

function testFunction(){

    console.log(this.variable);
}; var variable='Global Variable'; testFunction(); var packObject={variable:'Pack variable',testFunction:testFunction}; packObject.testFunction();

接下来通过Demo验证一下如何使用apply和call函数来改变this的指向:

function testFunction(){
console.log(this.variabale);
}; var variable='Global Variable'; var packObject={variable:'Pack Variable'}; testFunction.apply(window); testFunction.apply(packObject); testFunction.call(window); testFunction.call(packObject);

接下来在通过Demo演示一下函数对象的使用:

function testFunction(){
if(this===window){
console.log('This is window');
}
}; testFunction.innerFunction=function(){
if(this===testFunction){
console.log('This is testFunction');
}
if(this===window){
console.log('This is window');
}
}; ///
/// 等价于:window.testFunction();
///
testFunction(); testFunction.innerFunction(); testFunction.innerFunction.apply(window);
testFunction.innerFunction.call(window);

2.接下来介绍一下什么是原型(prototype):

prototype本质上还是Javascript的一个对象;每个函数都有一个默认的prototype属性;通过prototype可以扩展Javascript中的内建对象。

接下来通过Demo展示一下如何使用prototype:

function Person(name){
this.name=name;
}; Person.prototype={
getName:function(){
return this.name;
}
}; var testPerson=Person('test name'); console.log(testPerson.getName());

让我们来尝试一下如何使用prototype扩展Javascript内建对象:

Array.prototype.min=function(){
var min=this[0];
for(var index=0;index<this.length;index++){
min=(this[index]<min)?this[index]:min;
} return min;
}; console.log([3,6,2,4].min());

这个地方有个坑,当对Array进行扩展后,使用for-in循环会将数组循环出来

通过代码demo一下该陷阱(假设已经向Array扩展了min方法):

var arr=[2,4,3,6];
var total=0; for(var i in arr){
total+=parseInt(arr[i],10);
}
console.log(total);

通过demo程序演示一下如何解决该问题:

var arr=[2,4,6,3];
var total=0; for(var i in arr){
if(arr.hasOwnProperty(i)){
total+=parseInt(arr[i],10);
}
}
console.log(total);

3.接下来介绍一下什么是构造器(Constructor): a.constructor始终指向创建当前对象的构造(初始化)函数 b.每个函数都有一个默认的prototype属性,而这个prototype属性的constructor指向该函数

然后通过程序实例demo一下:

///
/// 等价于 var arr=new Array(2,4,6,5);
///
var arr=[2,4,6,5];
console.log(arr.constructor===Array); //true ///
/// 等价于 var Foo=new Function();
///
var Foo=function(){
};
console.log(Foo.constructor===Function); //true var obj=new Foo();
console.log(obj.constructor===Foo); true console.log(obj.constructor.constructor===Function); true

当constructor遇到prototype时,就会发生一种一下情况:
有上述可以知道每个函数都有默认的属性prototype,而这个默认的额prototype属性的constructor指向该函数

function Person(name){
this.name=name;
}; Person.prototype.getName=function(){
return this.name;
}; var obj=new Person('test person'); console.log(obj.constructor===Person); //true
console.log(Person.prototype.constructor===Person); //true console.log(obj.construtor.prototype.constructor===Person); //true

当我们重新定义prototype时,就会出现一个很奇怪的现象(以下实例是覆盖,上述实例是修改),constructor就会有所不同

function Person(name){
this.name=name;
}; Person.prototype={ getName:function(){
return this.name;
}
}; var obj=new Person('test person'); console.log(obj.constructor===Person); //false
console.log(Person.prototype.constructor===Person); //false console.log(obj.construtor.prototype.constructor===Person); //false

以下简单分析一下出现该现象的原因,覆盖操作等价于以下代码:

Person.prototype = new Object({getName:function () {
return this.name;
}});

而constructor始终指向创建自身的函数,因此Person.prototype.constructor===Object
我们可以通过重新覆盖construtor来解决该问题:

function Person(name) {
this.name = name;
};
Person.prototype = new Object({getName:function () {
return this.name;
}});
Person.prototype.constructor = Person;
var obj = new Person("test person");
console.log(obj.constructor === Person); // true
console.log(Person.prototype.constructor === Person); // true
console.log(obj.constructor.prototype.constructor === Person); // true

深入理解Javascript中this, prototype, constructor的更多相关文章

  1. 彻底理解JavaScript中的prototype、__proto__

    虽然在JavaScript里一切皆对象,但为了理解原型链系统,我们需要将JavaScript的对象分为对象和函数两大类.在此基础上,JavaScript的原型链逻辑遵从以下通用规则: 对象有__pro ...

  2. 深入理解javascript中实现面向对象编程方法

    介绍Javascript中面向对象编程思想之前,需要对以下几个概念有了解: 1. 浅拷贝和深拷贝:程序在运行过程中使用的变量有在栈上的变量和在堆上的变量,在对象或者变量的赋值操作过程中,大多数情况先是 ...

  3. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  4. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  5. 深入理解 JavaScript 中的 class

    在 ES6 规范中,引入了 class 的概念.使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代. 但是JS 中并没有一个真正的 class 原始类型, class 仅仅只 ...

  6. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  7. 全面理解Javascript中Promise

    全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非 ...

  8. 深入理解JavaScript中的作用域和上下文

    介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...

  9. 谈谈javascript中的prototype与继承

    谈谈javascript中的prototype与继承 今天想谈谈javascript中的prototype. 通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性 ...

随机推荐

  1. php实现递归的三种方式: 遍历文件夹实例

    递归函数是我们常用到的一类函数,最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去.实现递归函数可以采取什么方式呢?本文列出了三种基本方式.理解其原来需要一定的基础知识 ...

  2. UAC在注册表中的对应位置

    UAC在注册表中的对应位置 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System 相关键值设置: U ...

  3. AWS-CDH5.5安装-安装

    1.安装MySQL [root@ip---- mysql]# rpm -ivh MySQL-server--.el6.x86_64.rpm MySQL-client--.el6.x86_64.rpm ...

  4. Secondary NameNode:的作用?

    前言 最近刚接触Hadoop, 一直没有弄明白NameNode和Secondary NameNode的区别和关系.很多人都认为,Secondary NameNode是NameNode的备份,是为了防止 ...

  5. Extjs4 -- Ext.loader命名空间的配置

    初次使用extjs4的版本,在配置学习Ext.Loader()进行js文件的动态加载机制,由于各种原因导致多次失败,纠结2天,现将解决时出现的问题及需要注意事项进行记录 开发环境myeclipse8. ...

  6. Linux快捷键和别名

    一.设置别名 1使用命令行     alias 别名='命令'(只对本次登陆生效) 2.使用配置文件设置别名(永久生效) vi /root/.bashrc        打开系统别名配置文件,一般是用 ...

  7. 黑马程序员——OC基础 三种特性之封装

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) 三种特性之一封装 (一)set方法和get方法 1)  set方法 1&g ...

  8. VS 工程的 输出路径和工作路径的区别

    输出路径,是vs编译项目生成可执行文件的路径:工作路径是环境变量,比如我们在程序中写相对路径,就是以这个路径为基础的.在默认情况下,输出路径和工作路径都不写的话,默认是程序的bin下面的debug或者 ...

  9. 【转】输入/输出流 - 深入理解Java中的流 (Stream)

    基于流的数据读写,太抽象了,什么叫基于流,什么是流?Hadoop是Java语言写的,所以想理解好Hadoop的Streaming Data Access,还得从Java流机制入手.流机制也是JAVA及 ...

  10. STM32中断管理函数

    CM3 内核支持256 个中断,其中包含了16 个内核中断和240 个外部中断,并且具有256 级的可编程中断设置.但STM32 并没有使用CM3 内核的全部东西,而是只用了它的一部分. STM32 ...