Blogger Information
Blog 22
fans 0
comment 1
visits 17599
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
第八章深入理解函数
刘静的博客
Original
861 people have browsed it

第八章深入理解函数

函数声明的三种方式

1.函数的声明语句

  1. function fn(a,b,c){
  2. console.log(a);
  3. console.log(b);
  4. console.log(c);
  5. }
  6. fn(2,3);

2.函数的表达式:将一个匿名函数赋值给一个新的变量

  1. var hello = function(x,y){
  2. return x+y;
  3. }
  4. console.log(hello(3,5));
  1. var hello = function hel(x,y){
  2. console.log(hel===hello);
  3. return x+y;
  4. }
  5. console.log(x);
  6. hello(3,4);
  7. console.log(hello(3,5));
  8. console.log(hel(3,5));

[^个人理解: hello是变量名称,相当于函数的实参,既可以在函数内部也可以在函数外部使用]:
[^hel 是函数名称,相当于函数的形参,只能在函数的内部使用]:

3.Function 构造函数

  1. var fn = new Function('x', 'y', 'return x + y;');
  2. console.log(fn(3, 7));
  3. function fn(x,y){
  4. return x+y;
  5. }

深入理解函数返回值

应用在函数中

  1. function fn() {
  2. return {
  3. name: "MJJ",
  4. age: 18
  5. };
  6. alert(1);
  7. }
  8. // console.log(fn());//如果没有返回值,调用表达式的结果是undefined

并不是所有的函数中的return之后的代码都不执行(捕获现代代码异常)

  1. function testFinally(){
  2. try{
  3. // var a = 2;
  4. // var b = 3;
  5. // console.log(a+b);
  6. console.log(x);
  7. return 2;
  8. }catch(e){
  9. alert(e);
  10. //TODO handle the exception
  11. return 1;
  12. }finally{
  13. return 0;
  14. }
  15. }
  16. console.log(testFinally());

[^注意:不管调用成功与否,都会执行finally{return 0;}代码]:

一个函数可以有多个return语句

  1. function compare(x,y){
  2. if(x > y){
  3. return x - y;
  4. }else{
  5. return y - x;
  6. }
  7. }

如果函数调用时在前面加上new前缀,且返回值不是一个对象或者没有返回值,则返回该对象 (this)

  1. function fn(){
  2. console.log(this);
  3. this.a = 2;
  4. return 1;
  5. }
  6. var test = new fn();
  7. console.log(test);//类型 obj
  8. // 如果返回值是一个对象,则返回该对象
  9. function fn(){
  10. this.a = 2;
  11. return {a:1};
  12. }
  13. var test = new fn();
  14. console.log(test.constructor);

函数调用模式和方法调用模式

函数调用4种方式: 函数调用模式,方法调用模式,构造调用模式,间接调用模式

1.函数调用模式

  1. function add(x,y){
  2. 'use strict';
  3. // 在严格模式下,当前函数中this指向了undefined
  4. console.log(this);//在非严格模式,window对象
  5. return x + y;
  6. }
  7. var sum = add(3,4);
  8. console.log(sum);
  9. // 重写
  10. function fn(){
  11. this.a = 1;
  12. console.log(this);
  13. }
  14. fn();
  15. console.log(this);
  16. this.a = 5;
  17. console.log(this);

2.方法调用模式

[^注意:小心避免全局的属性重写带来的问题]:

  1. var obj = {
  2. a:1,
  3. // 这个fn称为obj对象的方法
  4. fn:function(){
  5. // console.log(this);
  6. // console.log('1');
  7. this.fn2();
  8. },
  9. fn2:function(){
  10. this.a = 2;
  11. }
  12. }
  13. obj.fn();
  14. // obj.fn2();
  15. console.log(obj.a);

3.构造函数调用模式

  1. function fn(x,y){
  2. this.a = x + y;
  3. }
  4. // this指向问题: 当做普通函数调用,this指向了window,当做构造函数调用,this指向当前的函数,当做对象的方法,这个this一般情况指向了当前的对象
  5. var obj = new fn(2,3);
  6. console.log(obj);
  7. var obj = {a:5};
  8. function fn(){
  9. console.log(this);
  10. this.a = 10;
  11. return obj;
  12. }
  13. var a = new fn;//等价于var a = new fn();
  14. console.log(a);

[^this指向问题: 当做普通函数调用,this指向了window,当做构造函数调用,this指向当前的函数,当做对象的方法,这个this一般指向了当前的对象]:

4.间接调用模式call({},1,2,3) apply({},[1,2,3])

  1. var obj = {
  2. a: 10
  3. };
  4. function sum(x,y){
  5. console.log(this);
  6. return x + y + this.a;
  7. }
  8. console.log(sum.call(obj,1,2));//call可以传一个对象 改变函数中this的问题
  9. console.log(sum.apply(obj,[1,2]));

[^call可以传一个对象 改变函数中this的问题]:

函数参数

函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数

  1. function add(x){
  2. return x + 1;
  3. }
  4. console.log(add(1));//2
  5. console.log(add('1'));//string类型的11
  6. console.log(add());//NaN
  7. console.log(add(1,2,3));//2
  8. // 同名形参
  9. function add(x,x,x){
  10. 'use strict';//严格定义函数
  11. return x;
  12. }
  13. console.log(add(1,2,3));
  14. // 参数个数
  15. // 实参比形参个数少,剩下的形参都将设置为undefined
  16. function add(x,y){
  17. console.log(x,y);
  18. }
  19. add(1,2,3,4);

实参比形参个数多,考虑arguments

  1. function add(x,y){
  2. console.log(arguments);
  3. // arguments它不是真正的数组,它是类数组,它能通过[]来访问它的每一个元素
  4. console.log(arguments[0],arguments[1],arguments[2]);
  5. console.log('实参的个数:'+ arguments.length);
  6. }
  7. add(1,2,3);

形参的个数

  1. console.dir(add.length);//console.dir 打开目录

函数重载现象

重载 :定义相同的函数名,传入的不同参数,实现不同的功能

[^在js中函数不存在重载现象 后面会覆盖前面的]:

  1. function add(a){
  2. return a + 100;
  3. }
  4. function add(a,b){
  5. return a + b + 100;
  6. }
  7. alert(add(10));
  8. // alert(add(10,20));

模拟重载现象

  1. function doAdd() {
  2. 第一种:if...else...写法
  3. if(arguments.length == 0){
  4. return 100;
  5. }else if(arguments.length == 1){
  6. return arguments[0] + 100;
  7. }else if(arguments.length == 2){
  8. return arguments[0] + arguments[1] + 100;
  9. }
  10. 第二种:switch写法
  11. switch (arguments.length) {
  12. case 0:
  13. return 100;
  14. break;
  15. case 1:
  16. return arguments[0] + 100;;
  17. break;
  18. case 2:
  19. return arguments[0] + arguments[1] + 100;;
  20. break;
  21. default:
  22. break;
  23. }
  24. }
  25. alert(doAdd());
  26. alert(doAdd(10));
  27. alert(doAdd(10, 20));

函数参数传递

1.基本数据类型

在向参数传递基本数据类型的值时,被传递的值会被复制到一个局部变量

  1. function add(num){
  2. num = num + 10;
  3. return num;
  4. }
  5. var count = 20;
  6. var result = add(count);
  7. console.log(result);
  8. console.log(count);

2.引用数据类型

在向参数传递引用数据类型的值时,会把这个值在内存中的地址复制给局部变量

  1. function setName(obj){
  2. obj.name = 'mjj';
  3. }
  4. var person = new Object();
  5. setName(person);
  6. console.log(person.name);
  1. function setName(obj){
  2. obj.name = 'mjj';
  3. console.log(person.name);
  4. obj = new Object();
  5. obj.name = 'test';
  6. console.log(person.name);//mjj
  7. }
  8. var person = new Object();
  9. setName(person);

函数属性

length属性

[^arguments对象中的length属性表示实参,而函数参数length属性表示的是形参的个数]:

  1. function add(x,y){
  2. console.log(arguments.length);//实参个数
  3. console.log(add.length);//形参个数
  4. }
  5. add(2,3,4,5);

name指的是当前函数的名字

  1. function fn(){};
  2. console.dir(fn.name);//fn
  3. var fn2 = function (){};
  4. console.log(fn2.name);//fn2
  5. var fn3 = function abc(){};
  6. console.log(fn3.name);//abc

prototype 属性

[^每一个函数都有一个prototype属性]:

  1. function fn(){};
  2. console.log(fn.prototype);//对象
  3. fn.prototype.a = 1;
  4. console.log(fn.prototype);

函数中apply和callf方法的使用

  1. function fn(){};
  2. var obj = new fn();
  3. fn.prototype.a = 1;//fn.prototype是父类,obj是子类,继承方法
  4. console.log(obj);
  5. // apply() call()
  6. // call({},1,2,3)
  7. // apply({},[])
  8. // 每个函数都包含两个非继承而来的方法
  1. window.color = 'red';
  2. var obj = {color:'blue'};
  3. function sayColor(){
  4. console.log(this.color);
  5. }
  6. sayColor();//red 因为当前的this指向了window
  7. sayColor.call(this);//red
  8. sayColor.call(window);//red
  9. sayColor.call(obj);//blue

在非严格模式下,如果我们使用call()或者是apply()方法,传入一个null或者undefined会被转换成一个全局window对象

[^在严格模式下,函数的指向始终是指定的值]:

  1. var color = 'red';
  2. function displayColor() {
  3. 'use strict';
  4. console.log(this);
  5. console.log(this.color);
  6. }
  7. displayColor.call(undefined);

call和apply方法的应用

1.找出数组的最大元素 Math.max() apply(null,)

  1. var max = Math.max(2,3,4,5,10);
  2. var arr = [22222,1,10,30,88];
  3. var arrMax = Math.max.apply(null,arr);//null或undefined会指向全局对象window
  4. console.log(arrMax);

2.将类数组转换成真正的数组

  1. function add(){
  2. console.log(arguments);
  3. // arguments.push(5);
  4. // apply() slice()
  5. var arr = Array.prototype.slice.apply(arguments);//复制数组 浅复制 继承Array.prototype 智能复制元素和 length,其他方法复制不了
  6. console.log(arr);
  7. }
  8. add(1,2,3);

3.数组追加

  1. var arr = [];
  2. Array.prototype.push.apply(arr,[1,2,3,4]);
  3. console.log(arr);
  4. Array.prototype.push.apply(arr,[8,9,0]);
  5. console.log(arr);

4.利用call和apply做继承

动物类 构造函数

  1. function Animal(name,age){
  2. this.name = name;
  3. this.age = age;
  4. this.sayAge = function(){
  5. console.log(this.age);
  6. }
  7. }
  8. // Cat
  9. function Cat(name,age){
  10. // 继承了Animal
  11. Animal.call(this,name,age);//把this指向了“var c = new Cat('小花',20)”的c实例对象
  12. }
  13. var c = new Cat('小花',20)
  14. c.sayAge();
  15. console.log(c.name);
  16. function Dog(){
  17. Animal.apply(this,arguments)
  18. }
  19. var d = new Dog('阿黄',18);
  20. console.log(d);

5.使用log代理console.log()

  1. function log(){
  2. console.log.apply(console,arguments);
  3. }
  4. log(d);

bind方法的使用

bind es5新增的方法,主要作用:将函数绑定到某个对象中,并且有返回值(一个函数)

  1. function fn(y){
  2. return this.x + y;
  3. }
  4. var obj = {
  5. x: 1
  6. }
  7. var gn = fn.bind(obj);//返回fn函数
  8. console.log(gn);
  9. console.log(gn(3));//4

常见的函数式编程技术- 函数柯里化

  1. function getConfig(colors,size,otherOptions){
  2. console.log(colors,size,otherOptions);
  3. }
  4. var defaultConfig = getConfig.bind(null,'#ff6700',1024*768);
  5. defaultConfig('123');
  6. defaultConfig('456');
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!