在Javascript面向对象编程中常常须要使用到this,prototype和constructor这3个关键字.编程
1.首先介绍一下this的使用:this表示当前对象;若是在全局中使用this,则this为当前页面对象window;若是在函数中使用this,则this为调用该函数的对象;可使用apply和call两个全局函数来改变this的指向。数组
接下来,首先经过几个demo程序验证一下:app
function testFunction(){ console.log(this.variable); }; var variable='Global Variable'; testFunction(); var packObject={variable:'Pack variable',testFunction:testFunction}; packObject.testFunction();
接下来经过Demo验证一下如何使用apply和call函数来改变this的指向:ide
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):this
prototype本质上仍是Javascript的一个对象;每一个函数都有一个默认的prototype属性;经过prototype能够扩展Javascript中的内建对象。spa
接下来经过Demo展现一下如何使用prototype: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内建对象:3d
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循环会将数组循环出来code
经过代码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