博客列表 >第八章深入理解函数

第八章深入理解函数

刘静的博客
刘静的博客原创
2020年08月25日 22:09:19873浏览

第八章深入理解函数

函数声明的三种方式

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');
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议