ECMAScript的函数是对象,函数名是指针数组
建立:浏览器
函数声明法:安全
- function sum (num1, num2) {
- return num1 + num2;
- }
函数表达式法:app
- var sum = function(num1, num2) {
- return num1 + num2;
- };
函数表达式法:这种不推荐,由于这种语法会致使解析两次代码(第一次解析常规ECMAScript代码,第二次解析传入构造函数中的字符串),从而影响性能ide
- var sum = new Function("num1", "num2", "return num1 + num2"); //不推荐
同时使用函数声明和函数表达式:这种语法会在Safari出错函数
- var sum = function sum () {}
因为函数名只是指针,因此以下:性能
- function sum(num1, num2){
- return num1 + num2;
- }
- alert(sum(10,10)); //20
- var anotherSum = sum;
- alert(anotherSum(10,10)); //20
- sum = null;
- alert(anotherSum(10,10)); //20
函数名是指针,因此没有重载:this
- function addSomeNumber (num) {
- return num + 100;
- }
- function addSomeNumber (num) {
- retrun num + 200;
- }
- var result = addSomeNumber(100); //300
上面代码其实是:spa
- function addSomeNumber (num) {
- return num + 100;
- }
- addSomeNumber = function (num) {
- retrun num + 200;
- }
- var result = addSomeNumber(100); //300
建立第二个函数时,改变了addSomeNumber的指向prototype
函数声明与函数表达式的一个区别:
解析器会率先读取函数声明,并使其在执行任何代码前可用;而函数表达式,必须等到解析器执行到所在行,才能被解释执行
- alert(sum(10,10)); //20
- function sum(num1, num2){
- return num1 + num2;
- }
若是改为以下,就会报错
- alert(sum(10,10)); //causes an error
- var sum = function(num1, num2){
- return num1 + num2;
- };
把函数当值使用:
将一个函数做为另外一个函数的结果返回
- function callSomeFunction(someFunction, someArgument){
- return someFunction(someArgument);
- }
- function add10(num){
- return num + 10;
- }
- var result1 = callSomeFunction(add10, 10);
- alert(result1); //20
- function getGreeting(name){
- return "Hello, " + name;
- }
- var result2 = callSomeFunction(getGreeting, "Nicholas");
- alert(result2); //Hello, Nicholas
从一个函数中返回另外一个函数,如给对象数组排序:(默认状况下,sort()会调用toString()方法)
- function createComparisonFunction(propertyName) {
- return function(object1, object2){
- var value1 = object1[propertyName];
- var value2 = object2[propertyName];
- if (value1 < value2){
- return -1;
- } else if (value1 > value2){
- return 1;
- } else {
- return 0;
- }
- };
- }
- var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
- data.sort(createComparisonFunction("name"));
- alert(data[0].name); //Nicholas
- data.sort(createComparisonFunction("age"));
- alert(data[0].name); //Zachary
函数内部属性:
函数内部有两个特点的对象 arguments 和 this
arguments:是一个类数组对象,包含传入函数的全部参数
callee:是arguments的属性,该属性是一个指针,指向拥有这个arguments对象的函数
下面是一个经典的阶乘例子:
- function factorial(num){
- if (num <= 1) {
- return 1;
- } else {
- return num * arguments.callee(num-1)
- }
- }
- var trueFactorial = factorial;
- factorial = function(){
- return 0;
- };
- alert(trueFactorial(5)); //120
- alert(factorial(5)); //0
this:引用的是函数据以执行的环境对象(当在网页的全局做用域中调用函数时,this对象引用的就是window)
- window.color = "red";
- var o = { color: "blue" };
- function sayColor(){
- alert(this.color);
- }
- sayColor(); //red
- o.sayColor = sayColor;
- o.sayColor(); //blue
caller:这个属性中保存着调用当前函数的函数的引用,若是在全局做用域中调用当前函数,它的值为null(Opera9.6版以前不支持该属性)
- function outer(){
- inner();
- }
- function inner(){
- alert(inner.caller);
- }
- outer(); //function outer(){
- // inner();
- //}
下面这种写法与上面同理,只是达到了更好的松耦合,这样函数名称能够变更而不用改变内部代码
- function outer(){
- inner();
- }
- function inner(){
- alert(arguments.callee.caller);
- }
- outer(); //function outer(){
- // inner();
- //}
注意:
1.这严格模式下,访问 arguments.callee 会致使错误。
2.ECMAScript5 还定义了 arguments.caller 属性,但在严格模式下也会致使错误,而在非严格模式下这个属性始终是undefined。定义这个属性是为了分清 arguments.caller 和 函数的caller属性。以上都是为了增强这门语言的安全性,这样第三方代码就不会在相同的环境里窥视其余代码了。
3.在严格模式下,不能给函数的caller属性赋值,不然会出错。
函数属性和方法:
因为在ECMAScript中,函数是对象,因此函数有属性和方法
length:表示函数但愿接收的命名参数的个数
- function sayName(name){
- alert(name);
- }
- function sum(num1, num2){
- return num1 + num2;
- }
- function sayHi(){
- alert("hi");
- }
- alert(sayName.length); //1
- alert(sum.length); //2
- alert(sayHi.length); //0
prototype:第6章
apply():用途是在特定的做用域中调用函数,实际上等于设置函数体内this对象的值?
需传入2个参数:该运行函数的做用域(this)、参数数组
- function sum(num1, num2){
- return num1 + num2;
- }
- function callSum1(num1, num2){
- return sum.apply(this, arguments); //因为在全局做用域中调用的,因此this指的是window对象
- }
- function callSum2(num1, num2){
- return sum.apply(this, [num1, num2]);
- }
- alert(callSum1(10,10)); //20
- alert(callSum2(10,10)); //20
注意:在严格模式下,未指定环境对象而调用函数,则this值不会转型为window。除非明确把函数添加到某个对象 或者 调用apply()或call(),不然this值将是undefined
call():用途是在特定的做用域中调用函数?
传入参数:该运行函数的做用域(this)、逐一列出参数
- function sum(num1, num2){
- return num1 + num2;
- }
- function callSum(num1, num2){
- return sum.call(this, num1, num2);
- }
- alert(callSum(10,10)); //20
apply()和call()真正的用武之地是扩充函数赖以运行的做用域,以下:
- window.color = "red";
- var o = { color: "blue" };
- function sayColor(){
- alert(this.color);
- }
- sayColor(); //red
- sayColor.call(this); //red
- sayColor.call(window); //red
- sayColor.call(o); //blue
使用apply()或call()来扩充做用域的最大的好处,就是对象不须要与方法有任何耦合关系(这跟以前那个版本比(讲this时),省下不少多余的步骤)
bind():把this值与该函数绑定
- window.color = "red";
- var o = { color: "blue" };
- function sayColor(){
- alert(this.color);
- }
- var objectSayColor = sayColor.bind(o);
- objectSayColor(); //blue
把o与objectSayColor的this绑定,因此调用时返回的是blue,而不是red,第22章
支持bind()的浏览器有IE9+、Firefox 4+、Chrome……
每一个函数继承的toLocaleString()、toString()、valueOf()都返回的函数的代码,因浏览器而异。