JS函数杂谈
来源:互联网 发布:美服lol汉化补丁mac 编辑:程序博客网 时间:2024/05/16 05:35
记录下JS中函数的对象特质、方法特质、构造函数特质,以及一些觉得必要的细节。
知识前提:对prototype和__proto__有基本的认识。测试环境:chrome。
函数是对象是方法也是构造函数
var func = function(a) { return a;}func.var_a = 1;console.log(func.var_a);//1console.log(func(2));//2
JS中一切皆对象,函数可以像普通对象一样被添加属性。同时,不影响其方法特质。
var func = function(a) { return a;}console.log(typeof func(2));//numberconsole.log(typeof new func(2));//object
第一行输出体现的是函数的方法特质,第二行就是构造函数的特质了。前者类似调用了一个方法,后者是构造出了一个新的对象。
所以,函数它就在那里,看你如何用它
对象的成员访问
用函数构造了一个对象,然后怎么访问对象中的成员呢。
var func = function(a) { this.inner_a = 1; return a;}func.prototype.pro_a = 1;func.var_a = 1;var obj_a = new func();var obj_b = new func();console.log(obj_a.var_a);//undefinedobj_a.inner_a = 2;console.log(obj_a.inner_a);//2console.log(obj_b.inner_a);//1
var_a是func的成员,而obj_a和obj_b是根据func构造而来的对象,自然无法访问func的成员。inner_a是obj_a和obj_b的成员,并且两者的inner_a不是同一个,因此改变a的自然不影响b的。
obj_a.pro_a = 2;console.log(obj_a.pro_a);//2console.log(obj_b.pro_a);//1
obj_a和obj_b本身都没有pro_a,然后给obj_a添加pro_a,再执行输出。a输出的是自身的pro_a,b输出的是prototype的pro_a。
func.prototype.pro_a = 2;console.log(obj_a.pro_a);//2console.log(obj_b.pro_a);//2
修改obj_a和obj_b构造函数func的prototype中的成员后的输出。所以,js中对对象的成员的遍历可见一斑。这应该是所谓原型链的范畴吧。
详解构造函数
var func = function(a) { return a;}var func_b = function() {}console.log(new func().__proto__ == func.prototype);//true
上述代码表明了,实例的__proto__确实是指向构造函数的prototype。JS遍历对象成员的时候依据的应该就是对__proto__的逐级遍历。
var func = function(a) { return new func_b();}var func_b = function() {}console.log(new func().__proto__ == func.prototype);//falseconsole.log(func().__proto__ == func.prototype);//falseconsole.log(new func().__proto__ == func_b.prototype);//trueconsole.log(func().__proto__ == func_b.prototype);//true
如果在func中返回func_b的实例。调用func()很好理解,会生成一个func_b的实例,console也证明这一点。如果生成func的实例,则生成后的实例其实就是func_b的实例。也就是说,此处func()和new func()效果一样。jQuery的构造函数就是这样的。
来点折腾-1
var func = function(a) { return func_b();}var func_b = function() {}console.log(new func().__proto__== func.prototype);//trueconsole.log(func().__proto__ == func.prototype);//抛异常console.log(new func().__proto__ == func_b.prototype);console.log(func().__proto__ == func_b.prototype);
如果在func中返回func_b的调用。由于func_b()不返回任何东西,那new func()生成的就是func的实例,自然第一条输出是true的。调用func()就和调用func_b效果一样,不返回任何东西,没有__proto__属性,自然抛异常。
来点折腾-2
var func = function(a) { return func_b;}var func_b = function() {}console.log(new func().__proto__== func.prototype);//falseconsole.log(func().__proto__ == func.prototype);//falseconsole.log(new func().__proto__ == func_b.prototype);//falseconsole.log(func().__proto__ == func_b.prototype);//falseconsole.log(new func() == func());//trueconsole.log(new (new func())().__proto__== func_b.prototype);//trueconsole.log(new (func())().__proto__== func_b.prototype);//true
如果在func中返回func_b。那么,func()和new func()其实返回的都是对象func_b。因此,new (func())()和new (new func())()相当于new func_b()。最后两行console输出也证明了这点。
小结
1,函数具备对象特质。
关于对象成员遍历会涉及原型链(proto在其中扮演关键角色),简单点说就是向上逐级遍历,类似java之类的语言中,子类的成员如果不存在会向父类遍历。
2,函数同时具备方法特质和构造函数特质。
当构造函数中返回了另外一个构造函数,或者返回一个新建的对象,则构造函数返回的不再是构造函数本身构造的实例。此处用instanceof运算符能更加直白的证明。因此,函数构造是有嵌套概念在的,jQuery的构造就利用了此点。
模拟下jQuery的构造
var func = (function(){ var func = function() { return new func_a(); } func.prototype.a = 2; var func_a = function() { } func_a.prototype = func.prototype; return func;})();console.log(func().a);//2
自调用匿名函数其实返回的是func_a的实例。为了能访问func的prototype中的内容,重置了func_a的prototype。
阅读全文
0 0
- JS函数杂谈
- 若干JS框架杂谈
- js技巧杂谈
- C-函数杂谈
- 杂谈笔记 函数
- opencv imshow()函数杂谈
- JS代码组织结构杂谈
- js,jquery的学习杂谈
- JS调用天气其他杂谈
- appcan及JS学习杂谈2
- 杂谈: 项目安全与js标准问题
- js字符串的各种方法杂谈
- 杂谈
- 杂谈
- 杂谈
- 杂谈
- 杂谈
- 杂谈
- Javassist实现动态代理
- 随心笔记
- 【爬虫】获取淘宝天猫商品的详细参数
- Form表单的onsubmit和renturn false
- 算法面试题
- JS函数杂谈
- 欢迎使用CSDN-markdown编辑器
- Struts2--使用JSP显示系统当前时间
- Myeclipse tomcat 部署项目报错
- 进化!将nodejs代码重构为ES6风格
- react(二)父子组件间的数据传递---prop
- SpannableString&SpannableStringBuilder定制文本
- WebSocket 协议
- Linux SSH远程文件/目录传输命令scp