关于函数
- 函数一段js代码 它只定义一次 但可以被执行或调用任意次 函数即对象
- 可以把函数赋值变量 或者作为参数传递给其他函数
- 因为是对象 所以可以设置属性 调用他们的方法
- js函数是参数化的 函数定义会包括一个称形参的标识符列表 这些参数像局部变量一样工作
- 函数调用会为形参提供实参的值 传参
- 如果函数挂载再一个对象上 作为对象的一个属性 称位对象的方法
- js函数 可以嵌套在其他函数中 这样他们就可以访问他们被定义时所处的作用域中的任何变量 闭包
函数的两个阶段: 定义阶段 调用阶段
//1.定义阶段
//声明式函数(具名函数)
function fn(){}
//赋值式函数
var fn=function(){}
//2.调用阶段:
//两种定义函数的方式不一样,但是调用方式一样, 都是函数名()
//声明式函数可以在定义之前调用,也可以在定义之后调用;
fn()
function fn(){
console.log(1)
}
fn()
//赋值式函数只能在定义之后调用
fn() //fn is not a function
var fn = function(){ //等号后面相当于简单的赋值;
console.log(1)
}
复制代码
函数的参数 es5 es6
形参(上):
~即定义在函数内部的变量(局部变量) + 只能载函数内部使用外部不可以使用 + 形参的值由函数调用时传递的实参决定
实参(下):
~函数调用的时候给形参进行赋值的 (传递值)
函数的传参:
//普通传参:
function fn(a,b){
console.log(a,b)
}
fn(10,20)
//使用变量传参(项目常用)
var m=10;
var n=10;
function fn(a,b){
console.log(a,b)
}
fn(m,n)
复制代码
参数的个数关系(即形参和实参)
1.两种参数一致 一一对应
实参多(下面的)
+ 获取行参的长度 arguments.length + 前面的一一对应,多出来的实参在函数体内没有变量接收,不能直接使用形参多(上面的)
+ 获取实参的长度 函数名.length + 前面的一一对应, 多出来的形参没有实参赋值,那么就是undefined;
函数默认参数值
//检测某个参数是否==undefined 没有传这个参数 就给他赋值一个
function makeKing(name){ //这里可以设置默认值的
neme = (typeof name!=="undefined")?name:"cdd";
return `king ${name} aa`
}
console.log(makeKing()) //king cdd aa
console.log(makeKing("Louis")) //king Louis aa
//var area = (width=1, height=1) => width*height ES6
复制代码
对象参数 比较常见在vue jq中 即函数的参数为对象的
var opt = {
width: 10,
height: 10
}
function area() {
this.width = opt.width || 1;
this.height = opt.height || 1;
return this.width * this.height
}
console.log(area(opt)); //100
复制代码
省略参数,参数默认值 ||短路
function sub(a, b) {
a = a || 0;
b = b || 0;
return a - b;
}
console.log(sub(5,1)); //4
复制代码
函数的返回值 为对象的时候
function Robot(name) {
this.name = name
}
Robot.prototype.init = function() {
return {
say: function () {
console.log('My name is ' + this.name)
}.bind(this),
dance: function(danceName) {
console.log('My dance name is ' + danceName)
}
};
}
var robotA = new Robot('A');
robotA.init().say(); // "My name is A"
var robotB = new Robot('B');
robotB.init().say(); // "My name is B"
复制代码
arguments;所有实参的集合,属于类数组;
arguments (形参列表)
js中每一个函数不包括箭头函数 内部能访问一个特别的变量arguments 这个变量维护所以传入 这个函数中的参数列表
arguments是函数内置的,所以在函数内部无需声明即可直接使用;
arguments变量不是一个数组 在语法上 他有数组的length 但它不从Array.prototype继承 实际上是一个对象
因此 无法对arguments 变量使用标准的数组方法 比如push pop…
虽然使用for循环是可以的 都是为了更好的使用数组方法 最好把它转为一个真正的数组
//转化为数组
//创建一个新的数组 包含所有的arguments 对象中的元素
Array.prototype.slice.call(arguments);
function fn(a,b){
for(var i=0;i<arguments.length;i++){
console.log(arguments[i])
}
}
fn(10,20) // 10 20
复制代码
arguments对象只定义在函数体中 从技术上来说 arguments对象不是数组 但是它拥有数值的属性和length属性
主要用途 用来判断有多少个参数传入函数 还可以指代未命名的参数 外加length属性 外加擦亮了二属性指代匿名函数本身
return返回 作用?
function fn(){
return 10*10 //return右边的代码会被返回;注:返回不等于输出
console.log(10) //return 后面的代码不会执行;
}
fn()
console.log(fn())
return false //针对on....出来的东西 阻止默认事件
//1.终止函数写在return后面的代码全部就不执行了
//2.给函数一个返回值;写在return右边的代码 + 即让函数执行完毕后由有个结果
//*不写ruturn 函数的返回值就是undefined
//*写了ruturn 没写返回内容返回值还是undefined
//*如果写了return 后面有东西,那么写什么,该函数的返回值就是什么;
//*如果写了return 但是后面没有东西,那么该函数的返回值是undefined
//*多个ruturn 只执行第一层的 后面代码不会执行
//看demo
//用return返回值:输出查看:
function f4(a,b){
return a+b
}
var rel=f4(10,30) //在此处赋值有个变量rel
console.log(rel) //40 赋值给一个变量,输出这个变量查看;
console.log(f4(10,30)) //或者输出的时候直接调用查看;
复制代码
函数中的this指向:
注:函数中的this指向,与函数的定义没有关系,只看函数的调用;
1.全局调用:this->window
函数名()
2.对象调用:this->点前面是谁就是谁
对象.函数()
var obj={
name:'小明',
fn:function(){
console.log(this)//obj
}
}
obj.fn()
3.定时器处理函数:this->window
setTimeout/clearInterval(function(){},20);
4.事件处理函数 this->事件源(谁身上的事件)
box.事件=function(){}
5.自执行函数: this->window
(function(a){
console.log(this)
})(10)
6.箭头函数没有this,他的this指向上下文,也就是外部作用域的this
var a=()=>{
console.log(this)
}
7.构造函数的 this->当前实例
function Person(name,age){
console.log(this)
this.name=name
}
var p1=new Person('小红',10)
复制代码
修改this指向
call()
语法:函数名.call()
1参 是你要改变的函数的his指向:不写或写null都为window;
第二个参数开始:依次是给函数传递参数
var obj={'name':'小明'}
fn.call(obj)表示fn函数在执行的时候,内部的this指向obj
注:元素.onclick=fn.call()这儿不能设置call;
apply()
语法:函数名.call()
1参 是你要改变的函数的this指向;
第二个参数是一个数组:数组里面每一项依次是给函数传递参数
fn.call(obj,[10,20,30])
bind()
says(say){
setInterval(function(){
console.log(this.tyep + "say" + say)
}.bind(this) ,1000)
}
复制代码
面试题call(),apply(),bind()区别 ?
call()
语法:函数名.call()
第一个参数是你要改变的函数的his指向:不写或写null都为window
第二个参数开始:依次是给函数传递参数
var obj={'name':'小明'}
fn.call(obj)表示fn函数在执行的时候,内部的this指向obj
注:元素.onclick=fn.call()这儿不能设置call;
apply()
语法:函数名.call()
第一个参数是你要改变的函数的his指向;
第二个参数是一个数组:数组里面每一项依次是给函数传递参数
fn.call(obj,[10,20,30])
bind ...
复制代码
箭头函数
1 特点就是更短 和解决匿名函数中this指向全局作用域的问题
2 箭头函数语法简洁 但是很多场景不适合使用
3 箭头函数不能使用arguments super和new.target 也不能使用构造函数 此外构造函数页没有portotype
4 是一种对函数表达式的缩写(也就是所说的赋值式函数) 对声明时函数没作用
语法
// 省略了function 关键字 ()=>{}
// 箭头函数没有this 里的this就是上下文(context) 就是箭头函数外部作用域的this
// +1箭头函数不受call/apply/bind的影响(修改函数this指向)也就是说箭头函数不能更改this
// 箭头函数在定义的时候就已经决定好了 定义好后任何方法都无法更改// **+2箭头函数内部没有arguments(所有实参的结合) **
// 箭头函数没有这个变量// +3箭头函数传递参数时候
// 如果只有一个行参可以不写小括号
// 如果没有行参或者两个以上,必须给小括号// +4箭头函数的函数体
// 如果只有一句话可以省略大括号{}
// 如果返回对象的话 加() //({a:1,b:2})
// 否则就必须写
// 当你省略{}的时候,函数会自动return// +5函数的参数默认值
// 函数在定义形参的时候给一个默认值(备胎)
// 如果你传递了实参, 就用你传递的实参
// 如果没传递实参 就会用定义的默认值
//
// 直接在形参的位置写 形参=默认值
// 箭头函数也可以设置默认值
// 如果你给箭头函数设置默认值
// 那么一个参数的时候,也要写小括号
这个程序猿太懒了,不想继续写了…在这里不列举了 大家可以预览git链接