javascript对象详解以及call、apply和bind的使用
来源:互联网 发布:php怎么连接数据库 编辑:程序博客网 时间:2024/04/29 20:21
因为项目需要用到javascript,boss说我以前是写Java的,写javascript上手快...只怪当时too young,于是误打误撞走进了javascript的世界。殊不知一入js深似海,更不知js比之Java就像雷峰塔比之雷锋、印度尼西亚比之印度、老婆饼比之老婆...
提起面向对象编程语言,往往想起的是C++、Java等强类型静态语言,以及Python等脚本语言。其中尤以Java为甚,Java is pure object oriented ,相较于C++,Java的main函数甚至都在一个类里面。这些语言都有一个共同点——他们都是基于类的面向对象。而提到javascript,很多人会怀疑它的面向对象特性,甚至认为javascript不是一门面向对象的语言,因为javascript没有类。事实上,javascript确实没有类,但javascript有对象,甚至只有对象,javascript的对象不是类的实例。大部分程序设计语言的面向对象都是基于类的,以至于人们形成一种惯性思维:对象都是类的实例。在javascript中这样的经验却是不适用的,所以我们更愿意称javascript是一门基于对象的语言。
I 创建
javascript对象实际上是一个由属性和值组成的关联数组。什么是关联数组呢?相较于平常意义上用数字作为索引的数组,关联数组可以用字符串作为索引。类似于键值对,对象的属性就是“键”,对象的值就是“值”咯。对象的值可以是任何数据类型,或者函数和其他对象。为什么对象的值可以是函数呢?说来话长,50多年前诞生了一种叫做函数式编程的东东(区别于命令式编程,与面向对象式编程更是风马牛不相及),函数式编程有很坚固的数学基础,跟什么lambda演算有关啦,一般人都不会懂的啦。我们javascript具有函数式编程的特点,所以函数是"第一等公民" !所谓"第一等公民",指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值,这些特性在C++和纯正的Java(之所以说纯正,是为了区别于scala等)里面是不可以想象的吧。好像扯远了,总之就是表达一个意思:函数可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
我们可以用以下代码创建一个简单的对象:
var obj = {};//创建一个空对象obj.prop1 = 'hey';//给第一个属性赋值obj.prop2 = true;obj.prop3 = function (str) { //函数也可以赋值给一个变量 return str;};console.log(obj.prop3('hello world'));//输出hello world
以上代码中,我们通过var obj = { };创建出一个对象并将其引用赋值给obj,随后通过obj.prop1 来获取其成员并赋值。除了通过var obj = { };创建一个对象,还可以用显式地用var obj=new Object();来创建一个对象。
既然上面已经提到javascript对象实质上就是一个关联数组,我们就来看看怎么用关联数组的方式创建对象,修改以上代码:
var obj = {};//创建一个空对象obj['prop1'] = 'hey';//使用关联数组引用赋值obj['prop2'] = true;obj['prop3'] = function (str) { //函数也可以赋值给一个变量 return str;};console.log(obj.prop3('hello world'));//输出hello world在javascript中,使用句点运算符和关联数组引用是等价的,使用关联数组的的一个好处是,在我们不知道对象的属性名称时,可以用变量作为关联数组的索引。例如:
var someProp = 'prop4';obj[prop4] = 100;通过以上代码你应该已经了解了如何去创建一个对象,但是在实际使用时,难免不会觉得繁琐冗杂。更加紧凑明了的方式如下:
var obj = { prop1: 'hey', prop2: true, prop3: function (str) { return str; }};
II 构造函数
前一节介绍的创建对象的方法可能让写惯了C++、Java的你大开眼界,对象竟然还能不靠构造函数来生成。仔细想想,我们可以察觉出前面方法的弱点:如果我们想批量地创建对象,能初始化若干固定好的属性、方法呢?不用担心,javascript为我们提供了构造函数,让我们看看如何用构造函数创建一个对象出来:
function Person(name, age) { this.name = name; this.age = age; this.introduceMyself = function () { console.log(this.name); };}
以上就是一个简单的构造函数,我们就可以用new语句来创建对象了:
var me = new Person("chendotjs", 21);接着就可以通过me访问该对象的方法和属性了。
III this指针
首先需要更正的是:在javascript里面并没有像C++一样的指针概念,这里所谓的this指针只是沿用一种传统的称法。javascript里的this“指针”和Java里面的this“指针”是很类似的。javascript里面任何函数的运行一定是被某个对象(包括全局变量)调用,而this指针就指向该对象,或者准确点说,是指向该对象的一个引用。来看一个例子:
var user1 = { name: 'user1', display: function () { console.log('I\'m ' + this.name); }};var user2 = { name: 'user2', func: user1.display};user1.display();//输出I'm user1user2.func();//输出I'm user2name = 'global';func = user1.display;func();//输出I'm globaljavascript的函数式编程特性使得函数可以像一般的变量一样赋值、传递。在上面的代码中,user2的func属性和global的func属性都是user1.display。当调用user1.display();、user2.func();和func();时,虽然调用的是同一个函数,但是this指针不属于任何一个函数,而取决于函数被调用时所属的对象。
事实上,在以上代码中,user1.display、user2.func和func是指向同一个函数实体的3个引用,引用之间的赋值不会复制出新的对象。这涉及到了“深拷贝和浅拷贝”的内容,将放在下一篇详细讨论。
关于this指针还有3个有趣的函数:call、apply以及bind,下面就介绍一下这3个函数:
1.call和apply
fun.call(thisArg[, arg1[, arg2[, ...]]])fun.apply(thisArg[,argsArray])其中,fun是函数的引用,thisArg是fun调用时的this指针指向的对象,arg1、arg2是argsArray是传给fun的参数。我们来看一个例子:
var user1 = { name: 'user1', display: function (food) { console.log(this.name + ' eats ' + food); }};var user2 = { name: 'user2'};user1.display('apples');//输出user1 eats applesuser1.display.call(user2, 'pears');//输出user2 eats pearsuser1.display.apply(user2, ['pears']);//输出user2 eats pears
2.bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])其中,fun是待绑定的函数,thisArg是fun调用时的this指针指向的对象,arg1、arg2是argsArray是传给fun的参数。bind方法的返回值是绑定了thisArg的fun,这点和call、apply是不同的。看一个例子:
var user1 = { name: 'user1', display: function () { console.log('I\'m ' + this.name); }};var user2 = { name: 'user2'};user2.func1 = user1.display;user2.func1();//输出I'm user2user2.func2 = user1.display.bind(user1);user2.func2();//输出I'm user1name = 'global';func = user1.display.bind(user2);func();//输出I'm user2在直接将user1.display赋值给user2.func1后,调用user2.func1()时,this指针指向user2,所以输出结果为“I'm user2”。user2.func2 使用了bind方法,将user1作为this指针绑定到user2.func2 ,调用user2.func2 ()时,this指针指向user1,所以输出为“I'm user1”。全局函数func也是同样的道理,这里省略具体分析。
var user1 = { name: 'user1', display: function (act, sth) { console.log(this.name + ' ' + act + ' ' + sth); }};var user2 = { name: 'user2'};user1.display('eats', 'food');//输出user1 eats foodvar func = user1.display.bind(user2, 'eats');func('apples');//输出user2 eats apples以上代码中,func函数将this指针绑定到user2,并将第一个参数绑定为‘eats’,之后在调用func时,只需要传入第三个参数即可。仔细想想,这个特性有很大的用处,通过这个特性可以在多次调用函数时,省略重复输入相同的参数。
3.bind的原理
var user1 = { name: 'user1', display: function () { console.log('I\'m ' + this.name); }};var user2 = { name: 'user2'};func1 = user1.display.bind(user2);func1();func2 = func1.bind(user1);func2();
I'm user2
fun.bind=function(obj){ var method=this; return function(){ method.call(obj); }}
var user1 = { name: 'user1', display: function () { console.log('I\'m ' + this.name); }};var user2 = { name: 'user2'};bind_byme = function (obj) { var method = this; return function () { method.call(obj); }};user1.display.bind_byme = bind_byme;//给user1.display加上自己写的bindfunc1 = user1.display.bind_byme(user2);func1();func1.bind_byme = bind_byme;//给func1加上自己写的bindfunc2 = func1.bind_byme(user1);func2();将自己作为编译器去解释以上代码,得到以下结果:
func1=function(){ user1.display.call(user2);};func2=function(){ func1.call(user1);};以上结果就很明了了,因为func1根本没有使用this指针,所以func2的bind函数根本不起作用,所以两次绑定是没有意义的。
- javascript对象详解以及call、apply和bind的使用
- JavaScript 中apply()、call()和bind()方法的使用
- apply()和call()、bind()的使用介绍
- 详解call(),apply()和bind()
- javascript中的call(),apply()以及bind()的用法
- JavaScript 中 call 、 apply 以及 bind 的用法
- javascript函数对象的内部方法call(), apply(), bind()
- JavaScript之apply,call以及bind方法
- 深入浅出Javascript中apply、call和bind以及它们的妙用
- Javascript中call,apply,bind方法的详解与总结
- JavaScript call、apply、bind、对象原型
- javascript中call apply bind详解
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- 如何选择一个好的视频转换为你
- Python学习日记(一)------------Using the Python Interpreter
- 如何选择和聘请名人00-6348
- 如何选择合适的地方学习PHP培训课程
- 如何选择合适的CRM软件,承诺精度
- javascript对象详解以及call、apply和bind的使用
- Lua查找表元素过程(元表、__index方法是如何工作的)
- 使用JAVA实现PHP中hash_hmac 函数
- 使用jchardet1.1 判断文件或网页编码
- How to remove Oracle JDK 在 ubunt上如何卸载JDK
- POJ 1273Drainage Ditches --网络流最大流模板题
- 使用JSCal2日历插件的步骤
- Oracle Apps修改用户密码的API
- InputStreamReader 和 FileReader联系与区别