首页
免费后端云服务
关于
Search
1
小程序后端入门系列视频教程【一-微信开发工具介绍】
9,812 阅读
2
微信小程序三级联动之多列选择器
9,710 阅读
3
小程序开发免费后端之神秘利器分享
9,632 阅读
4
Golang-开发企业级资源权限管理【第一步表设计】-1
9,174 阅读
5
学会微信服务端开发第一步
9,049 阅读
日常记录
日常
随笔
Bmob后端云
从零开始学物联网
Serverless实战驾校小程序
心邮
Serverless
向量数据库
登录
Search
Typecho
累计撰写
124
篇文章
累计收到
22
条评论
首页
栏目
日常记录
日常
随笔
Bmob后端云
从零开始学物联网
Serverless实战驾校小程序
心邮
Serverless
向量数据库
页面
免费后端云服务
关于
搜索到
1
篇与
的结果
2010-03-04
Javascript中this、prototype、constructor的理解
在Javascript面向对象的编程中我们常常会见到这三个关键字:this、prototype、constructor 。 对这三个关键字的理解是对Javascript面向对象编程理解的要点一、首先我们来说说“this”: 1、this表示当前对象; 2、如果在全局作用范围内使用this,则指代当前页面对象window; 3、如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用 4、我们还可以使用apply和call两个全局方法来改变函数中this的具体指向。在FireBug的控制台中验证一番吧:? 点击(此处)折叠或打开 // 定义一个全局函数 functionfoo(){ console.log(this.fruit); } // 定义一个全局变量,等价于window.fruit = "apple"; varfruit="apple"; // 此时函数foo中this指向window对象 // 这种调用方式和window.foo();是完全等价的 foo();// "apple" // 自定义一个对象,并将此对象的属性foo指向全局函数foo varpack={fruit:"orange",foo:foo}; // 此时函数foo中this指向window.pack对象 pack.foo(); 下面在来看看apply和call是如何来改变this的指向的 点击(此处)折叠或打开 // 定义一个全局函数 functionfoo(){ console.log(this.fruit); } // 定义一个全局变量 varfruit="apple"; // 自定义一个对象 varpack={fruit:"orange"}; // 等价于window.foo(); foo.apply(window);// "apple" // 此时foo中的this === pack foo.apply(pack); 因为在JavaScript中函数也是对象,所以我们可以看到如下的例子 点击(此处)折叠或打开 // 定义一个全局函数 function foo(){ if(this===window){ console.log("this is window."); } } // 函数foo也是对象,所以可以定义foo的属性boo为一个函数 foo.boo=function(){ if(this===foo){ console.log("this is foo."); }else{ if(this===window){ console.log("this is window."); } } }; // 等价于window.foo(); foo();//thisis window. // 可以看到函数中this的指向调用函数的对象 foo.boo();//thisis foo. // 使用apply改变函数中this的指向 foo.boo.apply(window);//thisis window. 二、什么是原型(prototype)1、prototype本质上还是一个JavaScript对象;2、每个函数都有一个默认的prototype属性;3、通过prototype我们可以扩展Javascript的内建对象如果这个函数被用在创建自定义对象的场景中,我们称这个函数为构造函数。 比如:点击(此处)折叠或打开 // 构造函数 functionPerson(name){ this.name=name; } // 定义Person的原型,原型中的属性可以被自定义对象引用 Person.prototype={getName:function(){ returnthis.name; }}; varzhang=newPerson("ZhangSan"); console.log(zhang.getName()); 我们可以通过prototype扩展Javascript的内建对象,例如: 点击(此处)折叠或打开 // 向JavaScript固有类型Array扩展一个获取最小值的方法 Array.prototype.min=function(){ varmin=this[0]; for(vari=1;i<this.length;i++){ if(this[i]<min){ min=this[i]; } } returnmin; }; // 在任意Array的实例上调用min方法 console.log([1,56,34,12].min()); 注意:这里有一个陷阱,向Array的原型中添加扩展方法后,当使用for-in循环数组时,这个扩展方法也会被循环出来。下面的代码说明这一点(假设已经向Array的原型中扩展了min方法):点击(此处)折叠或打开 vararr=[1,56,34,12]; vartotal=0; for(variinarr){ total+=parseInt(arr[i],10); } console.log(total); 解决方法也很简单: 点击(此处)折叠或打开 vararr=[1,56,34,12]; vartotal=0; for(variinarr){ if(arr.hasOwnProperty(i)){ total+=parseInt(arr[i],10); } } console.log(total); 三、构造器(constructor)1、constructor始终指向创建当前对象的构造(初始化)函数。 2、每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数我们来看个例子:点击(此处)折叠或打开 // 等价于 var arr = new Array(1, 56, 34, 12); vararr=[1,56,34,12]; console.log(arr.constructor===Array);// true // 等价于 var foo = new Function(); varFoo=function(){ }; console.log(Foo.constructor===Function);// true // 由构造函数实例化一个obj对象 varobj=newFoo(); console.log(obj.constructor===Foo);// true // 将上面两段代码合起来,就得到下面的结论 console.log(obj.constructor.constructor===Function); 但是当constructor遇到prototype时,有趣的事情就发生了。 我们知道每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数。如下例所示: 点击(此处)折叠或打开 functionPerson(name){ this.name=name; } Person.prototype.getName=function(){ returnthis.name; }; varp=newPerson("ZhangSan"); console.log(p.constructor===Person);// true console.log(Person.prototype.constructor===Person);// true // 将上两行代码合并就得到如下结果 console.log(p.constructor.prototype.constructor===Person); 当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖), constructor的行为就有点奇怪了,如下示例 点击(此处)折叠或打开 functionPerson(name){ this.name=name; } Person.prototype={getName:function(){ returnthis.name; }}; varp=newPerson("ZhangSan"); console.log(p.constructor===Person);// false console.log(Person.prototype.constructor===Person);// false console.log(p.constructor.prototype.constructor===Person); 为什么呢? 原来是因为覆盖Person.prototype时,等价于进行如下代码操作: 点击(此处)折叠或打开 Person.prototype=newObject({getName:function(){ returnthis.name; }}); 而constructor始终指向创建自身的构造函数,所以此时Person.prototype.constructor === Object怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可:点击(此处)折叠或打开 functionPerson(name){ this.name=name; } Person.prototype=newObject({getName:function(){ returnthis.name; }}); Person.prototype.constructor=Person; varp=newPerson("ZhangSan"); console.log(p.constructor===Person);// true console.log(Person.prototype.constructor===Person);// true console.log(p.constructor.prototype.constructor===Person); http://jiangzhengjun.javaeye.com/blog/486450
2010年03月04日
30 阅读
1 评论
0 点赞