javascript语言精粹:函数
2012-08-25 16:23 youxin 阅读(292) 评论(0) 编辑 收藏 举报Functions in JavaScript are objects. Objects are collections of name/value pairs having
a hidden link to a prototype object. Objects produced from object literals are
linked to Object.prototype. Function objects are linked to Function.prototype
(which is itself linked to Object.prototype). Every function is also created with two
additional hidden properties: the function’s context and the code that implements
the function’s behavior.】
javascript函数是对象。对象是“键值”对的集合并拥有一个连到原型对像的隐藏链接。对象字面量
产生的对象链接到Object.prototype,函数对象链接到Function.prototype(该原型对象本身链接
到Object.prototype).每个函数在创建时会附加2个隐藏属性:函数的上下文和实现函数行为的代码。
Every function object is also created with a prototype property. Its value is an object
with a constructor property whose value is the function. This is distinct from the
hidden link to Function.prototype. The meaning of this convoluted construction will
be revealed in the next chapter.
每个函数对象在创建时也随配有一个prototype属性,他的值是一个拥有constructor属性且值为该函数的对象。
这和隐藏链接到Function.prototype完全不同,
Since functions are objects, they can be used like any other value. Functions can be
stored in variables, objects, and arrays. Functions can be passed as arguments to
functions, and functions can be returned from functions. Also, since functions are
objects, functions can have methods.
The thing that is special about functions is that they can be invoked.
函数的与众不同不同在于他可以被调用。
Function Literal 函数字面量
Function objects are created with function literals:
// Create a variable called add and store a function
// in it that adds two numbers.
var add = function (a, b) {
return a + b;
};
There are four patterns of invocation in JavaScript: the
method invocation pattern, the function invocation pattern, the constructor invocation
pattern, and the apply invocation pattern. The patterns differ in how the bonus
parameter this(额外的参数this) is initialized。
方法调用模式:
When a function is stored as a property of an object, we call it a method. When a
method is invoked, this is bound to that object.当一个方法被调用时,this被绑定到该对象。
If an invocation expression contains a refinement (that is, a . dot expression or [subscript] expression), it is
invoked as a method:
// Create myObject. It has a value and an increment // method. The increment method takes an optional // parameter. If the argument is not a number, then 1 // is used as the default. var myObject = { value: 0, increment: function (inc) { this.value += typeof inc === 'number' ? inc : 1; } }; myObject.increment( ); document.writeln(myObject.value); // 1 myObject.increment(2); document.writeln(myObject.value); // 3
A method can use this to access the object so that it can retrieve values from the
object or modify the object. The binding of this to the object happens at invocation
time. This very late binding makes functions that use this highly reusable. Methods
that get their object context from this are called public methods.
方法可以使用this去方法对象,所以他能从对象中 取值或修改该对象,this到对象的绑定发生在调用的时候,这个
‘超级“迟邦定使得函数可以对this高度复用。通过this可取得他们所属对象的上下文的方法称为公共方法。
The Function Invocation Pattern
When a function is not the property of an object, then it is invoked as a function:
var sum = add(3, 4); // sum is 7
When a function is invoked with this pattern, this is bound to the global object.
This was a mistake in the design of the language. Had the language been designed
correctly, when the inner function is invoked, this would still be bound to the this
variable of the outer function. A consequence of this error is that a method cannot
employ an inner function to help it do its work because the inner function does not
share the method’s access to the object as its this is bound to the wrong value. Fortunately,
there is an easy workaround. If the method defines a variable and assigns it
the value of this, the inner function will have access to this through that variable. By
convention, the name of that variable is that:
当采用函数调用时,this被绑定到全局对象。这是语言设计上的一个错误。倘若语言设计正确,那么当内部函数被调用时,this
应该仍然绑定到外部函数的this变量。这个设计错误的后果就是方法不能利用内部函数来帮助他工作,因为内部函数的this被
绑定到了错误的值,所有不能共享该方法对对象的访问权,幸运的是,有一个很容易的解决方案:如果该方法定义一个变量并
给他赋值为this,那么内部函数就可以通过那个变量访问到this,按照约定,我把那个变量命名为that。
// Augment myObject with a double method. myObject.double = function ( ) { var that = this; // Workaround. var helper = function ( ) { that.value = add(that.value, that.value); }; helper( ); // Invoke helper as a function. }; // Invoke double as a method. myObject.double( ); document.writeln(myObject.value);
如果我们在helper函数中使用this,this则是全局变量的一个熟性。由于window没有value的属性,所有错误。
The Constructor Invocation Pattern 构造器调用模式
JavaScript is a prototypal inheritance language. That means that objects can inherit
properties directly from other objects. The language is class-free.
js是一个基于原型继承的语言。这意味着对象可以直接从其他对象继承属性。该语言是无类型的。
This is a radical departure from the current fashion. Most languages today are classical.
Prototypal inheritance is powerfully expressive, but is not widely understood.
JavaScript itself is not confident in its prototypal nature, so it offers an object-making
syntax that is reminiscent of the classical languages. Few classical programmers
found prototypal inheritance to be acceptable, and classically inspired syntax
obscures the language’s true prototypal nature. It is the worst of both worlds.
If a function is invoked with the new prefix, then a new object will be created with a
hidden link to the value of the function’s prototype member, and this will be bound
to that new object.
The new prefix also changes the behavior of the return statement. We will see more
about that next.
如果在一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype成员的新对象,同时,
this会被绑定到新对象上。
new也会改变return语句的行为。
// Create a constructor function called Quo. // It makes an object with a status property. var Quo = function (string) { this.status = string; }; // Give all instances of Quo a public method 给所有Quo的实例添加一个方法
// called get_status. Quo.prototype.get_status = function ( ) { return this.status; }; // Make an instance of Quo. var myQuo = new Quo("confused"); document.writeln(myQuo.get_status( )); // confused
Functions that are intended to be used with the new prefix are called constructors. By
convention, they are kept in variables with a capitalized name. If a constructor is
called without the new prefix, very bad things can happen without a compile-time or
runtime warning, so the capitalization convention is really important.
Use of this style of constructor functions is not recommended. We will see better
alternatives in the next chapter.
The Apply Invocation Pattern apply调用模式
Because JavaScript is a functional object-oriented language, functions can have
methods.
The apply method lets us construct an array of arguments to use to invoke a function.
It also lets us choose the value of this. The apply method takes two parameters.
The first is the value that should be bound to this. The second is an array of
parameters.
// Make an array of 2 numbers and add them. var array = [3, 4]; var sum = add.apply(null, array); // sum is 7 // Make an object with a status member. var statusObject = { status: 'A-OK' }; // statusObject does not inherit from Quo.prototype, // but we can invoke the get_status method on // statusObject even though statusObject does not have // a get_status method. var status = Quo.prototype.get_status.apply(statusObject); // status is 'A-OK'
想