文章目录
一、函数
1.函数的声明
-
函数的声明语句
function fn(a,b,c){ console.log(a); console.log(b); console.log(c); } fn(2,3);
-
函数的表达式
var hello = function(x,y){ return x+y; } console.log(hello(3,5)); // 个人理解: hello是变量名称,相当于函数的实参,既可以在函数内部也可以在函数外部使用 // hel 是函数名称,相当于函数的形参,只能在函数的内部使用 var hello = function hel(x,y){ console.log(hel===hello); return x+y; } // console.log(x); hello(3,4); // console.log(hello(3,5)); // console.log(hel(3,5));
-
Function 构造函数
var fn = new Function('x', 'y', 'return x + y;'); console.log(fn(3, 7)); // function fn(x,y){ // return x+y; // }
2.函数返回值
-
return 如果没有返回值,调用表达式结果是 undefined,其后面的函数并不执行
function fn() { return { name: "MJJ", age: 18 }; alert(1); } // console.log(fn());//如果没有返回值,调用表达式的结果是 undefined console.log(fn());
-
try{} catch(e){} finally{}情况
并不是所有的函数中的return之后的代码都不执行
function testFinally(){ try{ // var a = 2; // var b = 3; // console.log(a+b); console.log(x); return 2; }catch(e){ alert(e); //TODO handle the exception return 1; }finally{ return 0; } } console.log(testFinally());
-
一个函数多个return
function compare(x,y){ if(x > y){ return x - y; }else{ return y - x; } }
-
在调用函数时,使用 new 前缀时,
- 返回值不是一个对象或者没有返回值时,则返回该对象(this)
- 返回对象情况,则就是对象
// 如果函数调用时在前面加上new前缀,且返回值不是一个对象或者没有返回值,则返回该对象 (this) function fn(){ console.log(this); this.a = 2; //return {b:23}; 返回对象情况,则就是对象 return 0; } var test = new fn(); //console.log(test); // constructor 构造函数,每个对象都有这个属性 console.log(test.constructor)
3.函数调用
相同的函数,不同的调用方式,会出现不同的结果,特别是 this 指向问题
-
普通函数调用模式
严格模式,在代码中 + ‘use strict’
function add(x,y) { 'use strict'; // 在严格模式,this 指向 underfined console.log(this);// 在非严格模式,this指向 window 对象 return x + y; } var sun = add(3,4); console.log(sum); // 在非严格模式下,可能会出现重写情况! // 重写 function fn(){ this.a = 1; console.log(this); } fn(); console.log(this); this.a = 5; console.log(this); // 以上就是非严格下,在函数中,更改到了window 的属性 // 注意:小心避免全局的属性重写带来的问题
-
方法调用模式
// 方法调用模式 var obj = { a:1, // 这个fn称为obj对象的方法,this指向的是:obj fn:function(){ console.log(this); // console.log('1'); this.fn2(); }, fn2:function(){ this.a = 2; } } obj.fn(); // obj.fn2(); console.log(obj.a);
-
构造调用模式
构造调用:new 一个方法
this指向问题: 当做普通函数调用,this指向了window,当做构造函数调用,this 指向当前的函数,当做对象的方法,这个 this 一般情况指向了当前的对象
// 3.构造函数调用模式 function fn(x,y){ this.a = x + y; } // this指向问题: 当做普通函数调用,this指向了window,当做构造函数调用,this指向当前的函数,当做对象的方法,这个this一般情况指向了当前的对象 var obj = new fn(2,3); console.log(obj); var obj = {a:5}; function fn(){ console.log(this); this.a = 10; return obj; } var a = new fn;//等价于var a = new fn(); console.log(a);
-
间接调用模式
改变this的指向方法: call({},参数1,参数2,…)、apply({},[参数1,参数2…])
将调用的函数方法的 this 指向,指向为 call()、apply()的第一个对象
// 间接调用模式call({},1,2,3) apply({},[1,2,3]) var obj = { a: 10 }; function sum(x, y) { console.log(this); return x + y + this.a; } // console.log(sum()); console.log(sum.call(obj, 1, 2)); console.log(sum.apply(obj, [1, 2]));
4.函数参数
- add 和 add() 是不一样的
- add 表示的是函数 log返回的是代码,dir返回的是实际的函数对象属性和方法
- add() 表示的是函数的结果内容 log返回的是结果,dir返回的直接是内容,但是结果的内容就是结果0
- log 和 dir 的区别?
- log语句打印的是结果,直接显示信息;
- dir语句打印的是内容,对显示对象的所有属性和方法。
参考本节的 参数个数
arguments : arguments它不是真正的数组,它是类数组,它能通过[]来访问它的每一个元素
console.log(arguments);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFqmNkoY-1635122046289)(C:/Users/13059/AppData/Roaming/Typora/typora-user-images/image-20211007101752744.png)]
-
函数不在意有多少个参数、参数是什么数据类型,甚至可以不传参数
// 函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数 function add(x) { return x + 1; } console.log(add(1)); console.log(add('1')); console.log(add());//NaN console.log(add(1, 2, 3));
-
同名的参数(形参)也是可以的,只有最后的参数有效。其余被覆盖
function add(x,x,x){ 'use strict'; return x; } console.log(add(1,2,3));
-
参数个数
实参比形参个数少时,其余形参都将被设置为 undefined
function add(x,y){ console.log(x,y); } add(1,2,3,4);
实参比形参个数多时,其余实参无效
解决办法:使用 arguments
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qaThfcdh-1635122046293)(C:/Users/13059/AppData/Roaming/Typora/typora-user-images/image-20211007101742754.png)]
// 实参比形参个数多,考虑arguments function add(x,y){ console.log(arguments); // arguments它不是真正的数组,它是类数组,它能通过[]来访问它的每一个元素 console.log(arguments[0],arguments[1],arguments[2]); console.log('实参的个数:'+ arguments.length); return 0; } add(1,2,3); // add 和 add() 是不一样的, // add 表示的是函数 log返回的是代码,dir返回的是实际的函数对象属性和方法, // add() 表示的是函数的结果内容 log返回的是结果,dir返回的直接是内容,但是结果的内容就是结果0 // log 和 dir 的区别? // log语句打印的是结果,直接显示信息; // dir语句打印的是内容,对显示对象的所有属性和方法。 console.dir(add()); // 形参的个数 console.dir(add.length);
-
JS中函数不存在 重载,会被覆盖
// 重载 :定义相同的函数名,传入的不同参数,实现不同的功能
为解决 : JS 函数不存在重载,会被后续同函数名方法给覆盖
function add(a) { return a + 100; } function add(a, b) { return a + b + 100; } alert(add(10));
可行方式:利用 arguments 类数组特性,实现相同效果,迂回实现
function doAdd() { /* if(arguments.length == 0){ return 100; }else if(arguments.length == 1){ return arguments[0] + 100; }else if(arguments.length == 2){ return arguments[0] + arguments[1] + 100; } */ switch (arguments.length) { case 0: return 100; break; case 1: return arguments[0] + 100; break; case 2: return arguments[0] + arguments[1] + 100; break; default: break; } } alert(doAdd()); alert(doAdd(10)); alert(doAdd(10, 20));
5.函数参数传递
1.基本数据类型
在向参数传递基本数据类型的值时,被传递的值会被复制到一个局部变量–不改变原值
- 如以下 Code,执行过程如图:
function add(num){ num = num + 10; return num; } var count = 20; var result = add(count); console.log(result); console.log(count);
- Javascript 执行过程
2.引用数据类型
在向参数传递引用数据类型的值时,会把这个值在内存中的地址复制给局部变量–原值会发生变化
- 最基础版
- Code
// 2.引用数据类型 // 在向参数传递引用数据类型的值时,会把这个值在内存中的地址复制给局部变量 function setName(obj){ obj.name = 'mjj'; } var person = new Object(); setName(person); console.log(person.name);
- 执行图
- 多个
- Code
function setName(obj) { obj.name = 'mjj'; console.log(person.name); obj = new Object(); obj.name = 'test'; console.log(person.name); } var person = new Object(); setName(person);
- 执行图
6.函数属性
1.length 属性
arguments对象中的length属性表示实参,而函数参数length属性表示的是形参的个数
// length属性 // arguments对象中的length属性表示实参,而函数参数length属性表示的是形参的个数 function add(x, y) { console.log(arguments.length); console.log(add.length); } add(2, 3, 4, 5); console.dir(add)
2. name 属性
表示当前函数的名字
// name指的是当前函数的名字 function fn(){}; console.dir(fn.name);//fn var fn2 = function (){}; console.log(fn2.name);//fn2 var fn3 = function abc(){}; console.log(fn3.name);//abc
3.prototype 属性 原型
每一个函数都有一个prototype属性
// 每一个函数都有一个prototype属性 function fn(){}; console.log(fn.prototype); fn.prototype.a = 1; console.log(fn.prototype);
7.函数方法:call、apply、bind
改变this的指向方法: call({},参数1,参数2,…)、apply({},[参数1,参数2…]) bind({})返回一个函数
将调用的函数方法的 this 指向,指向为 call()、apply()的第一个对象
1.call、apply()方法
-
基本概念
call({},1,2,3)
apply({},[])
每个函数都包含两个非继承而来的方法 -
使用代码
// apply() call() // call({},1,2,3) // apply({},[]) // 每个函数都包含两个非继承而来的方法 window.color = 'red'; var obj = {color: 'blue'}; function sayColor() { console.log(this.color); } sayColor();//red 因为当前的this指向了window sayColor.call(this);//red sayColor.call(window);//red sayColor.call(obj);//blue
-
严格模式和非严格模式下:call、apply 传null undefined
- 在非严格模式下,如果我们使用call()或者是apply()方法,传入一个null或者undefined会被转换成一个全局window对象
- 在严格模式下,函数的指向始终是指定的值
// 在非严格模式下,如果我们使用call()或者是apply()方法,传入一个null或者undefined会被转换成一个全局window对象 // 在严格模式下,函数的指向始终是指定的值 var color = 'red'; function displayColor() { 'use strict'; console.log(this); console.log(this.color); } displayColor.call(undefined);
-
call、apply()方法的实际运用
-
找出数组的最大元素,Math.max()、apply(null,参数…)
// 1.找出数组的最大元素 Math.max() apply(null,) var max = Math.max(2,3,4,5,10); var arr = [22222,1,10,30,88]; var arrMax = Math.max.apply(null,arr); console.log(arrMax);
-
将类数组转换成真正的数组 ?slice.apply ?
slice(开始参数,结束参数) ,将数组从start,开始end结束的数组,并不影响原数组,从原数组复制到新数组,
function add() { console.log(arguments); // arguments.push(5); // apply() slice() var arr = Array.prototype.slice.apply(arguments); console.log(arr); } add(1, 2, 3);
-
数组追加
var arr = []; Array.prototype.push.apply(arr, [1, 2, 3, 4]); console.log(arr); Array.prototype.push.apply(arr, [8, 9, 0]); console.log(arr);
-
利用call和apply做继承 ?call apply?
function Animal(name, age) { this.name = name; this.age = age; this.sayAge = function () { console.log(this.age); } } // Cat function Cat(name, age) { // 继承了Animal Animal.call(this, name, age);//把this指向了43行的c实例对象 } var c = new Cat('小花', 20) c.sayAge(); console.log(c.name); function Dog() { Animal.apply(this, arguments) } var d = new Dog('阿黄', 18); console.log(d);
-
使用log代理console.log()
arguments 形参,类数组,存放传来的参数
function log() { console.log.apply(console, arguments); }
-
2.bind() 方法 和call apply类似,bind有返回值(一个函数)
-
bind es5新增的方法,主要作用:将函数绑定到某个对象中,并且有返回值(一个函数)
// bind es5新增的方法,主要作用:将函数绑定到某个对象中,并且有返回值(一个函数) function fn(y) { return this.x + y; } var obj = { x: 1 } var gn = fn.bind(obj); // console.log(gn); // 返回 fn(y){...} console.log(gn(3)); // 4
-
???常见的函数式编程技术- 函数柯里化🔴
// 常见的函数式编程技术- 函数柯里化 function getConfig(colors, size, otherOptions) { console.log(colors, size, otherOptions); } var defaultConfig = getConfig.bind(null, '#ff6700', 1024 * 768); defaultConfig('123'); defaultConfig('456'); // 函数 作用域 闭包 this 面向对象编程(封装 继承 多态)