第十六节:特殊对象—函数详解

1、函数特点及常见名词解释

  • 函数特点:一个地方定义,多个地方执行
  • 函数的参数化:函数的定义和使用过程中可以传递参数到函数中,传递参数的这个过程被称之为函数的参数化。
  • 形参:函数定义的参数。
  • 实参:函数运行时接收到的参数。

举例说明:下面代码中a,b称之为形参,使用函数sum时传入的1,2称之为实参。

function sum(a,b){
  return a+b;
}
sum(1,2);

2、函数的创建

① 使用 函数声明语句 创建函数(结尾可不使用分号;大括号即表示函数的结束,如果加上;会被当成空语句,也不会报错)

function name(参数 1, 参数 2, 参数 3) {
   要执行的代码
}
//这种创建方式,函数默认有一个name属性
function ok(){}
ok.name;//结果 ok,即函数的名字

② 使用 函数表达式语句 创建函数,将没有名字的函数赋值给变量

var a = function(参数 1, 参数 2, 参数 3){
   要执行的代码
}
//命名函数表达式
var f = function fun(参数 1, 参数 2, 参数 3){
   要执行的代码
}
f.name;//fun

区别:

  • 函数声明语句:存在声明提前的现象。整个函数都会被提前,但是还是建议先声明后使用。
  • 函数表达式语句:将函数赋值给一个变量,只会将变量提前,函数不会被提前
  • 命名函数:表达式函数体内可以访问此函数,函数体外无法访问;函数声明的函数:函数体内和函数体外均可访问到此函数

备注:严格模式(“use strict”;es5新增)下,不允许在语句块中使用函数声明语句中声明函数
如果必须在for循环或者if-else这些语句块中使用函数,建议使用函数表达式语句

命名函数表达式函数体内可访问到此函数,函数体外无法访问的特性可用于递归
但ie8在函数外也能访问次函数,为了解决此问题,可以将变量和函数名起同一个名字

var a = function sum(){
   console.log(sum);
}
a();//运行函数可以打印出来sum是一个函数
sum;//函数体外访问sum返回sum is not defined
var a = function a(){
console.log(1);
}
a;//ƒ a(){console.log(1);}
a();//1

ES6扩展 —— 箭头函数(匿名函数的另一个简写)

var a = function(){}
//使用箭头函数可改造为下面的写法
var a= (参数名1,参数名2) =>{
   要执行的代码
}
const sum1 = (x,y)=>{
return x+y;
}
sum1(1,5);//6
//只有一个参数,小括号也可以省略
var a= item=>{
   要执行的代码
}
//只有一行代码,大括号可省略,return也可省略
const sum1 = (x,y)=> x+y;

箭头函数特点:

  • 箭头函数不会创建自己的上下文环境,没有this指向
  • 箭头函数是一个匿名函数
  • 箭头函数没有arguments对象(正常函数,arguments 是一个对应于传递给函数的参数的类数组对象,arguments[0]对应第一个参数,以此类推)
  • 使用前请检查浏览器是否支持es6
//this指向问题,在箭头函数中,其实是没有this指向的,当需要用到this时,会通过当前的作用域链向上层的作用域内进行寻找,找它上层的作用域内this的指向
 const oBtn = document.querySelector('#btn');
oBtn.addEventListener('click', function(){
    console.log(this); //id为btn的button按钮
    this.style.backgroundColor = '#f00';
})
const oBtn2 = document.querySelector('#btn2');
oBtn2.addEventListener('click', ()=>{
    console.log(this);//window对象
    this.style.backgroundColor = '#f00';
})

箭头函数什么场景不能使用:

  • 作为事件的回调函数,尽量不要使用,因为this指向有偏差
  • 对象中的方法,不能使用箭头函数;es6中对象的方法有一个简写,参照下面示例
  • 需要使用arguments对象时,不能使用箭头函数
  • 不能使用箭头函数作为构造函数
  • 不能使用箭头函数定义原型上的方法
const obj = {
    mainName:'xiecheng',
    showName: function(){ //es6之前的写法
        console.log(this.mainName);
    },
    edit: ()=>{ //箭头函数写法,this指向错误
        console.log('hello '+this.mainName+'!');
    }es6fun(){ //es6方法简写
   	 console.log('hello '+this.mainName+'!');
    }
}
obj.showName(); //xiecheng
obj.edit(); //hello undefined!,window.mainName为undefined,所以返回undefined;
es6fun();//hello xiecheng!
//构造函数
function Course(name, price){
   this.name = name;
   this.price = price;
}
//为构造函数的prototype增加一个方法,此方法也不能使用箭头函数
Course.prototype.study = function(){
   console.log(`我要学习${this.name},价格是:${this.price}`)
}//反引号(``)为es6的新语法,模板字符串
//改造为箭头函数会报错:Course is not a constructor
//const Course = (name, price)=>{
//   this.name = name;
//   this.price = price;
//}
var c1 = new Course('es', 500);
arguments 是一个对应于传递给函数的参数的类数组对象(类数组,而非数组,除了length属性和索引元素之外没有任何Array属性)
function a(a,b){
console.log(arguments);
console.log('第一个参数:',arguments[0]);
return a+b;
}
a(1,2);//结果如下
//Arguments { 0: 1, 1: 2, … }
//第一个参数: 1
//3

//将arguments转换成数组
function a(a,b){
console.log('转换成数组的arguments:',Array.prototype.slice.call(arguments));
return a+b;
}
a(3,4);//结果如下
//转换成数组的arguments:Array [ 3, 4 ]
//7

构造函数详解参考

③es6创建函数,函数生成器

//每次点击按顺序打印数组的值
<button onclick="x.next()">按钮</button>
<script>
function* mes(){
    var arr = ['第一句','第二句','第三句','第四句'];
    for(let i=0;i<arr.length;i++){
        console.log(arr[i]);
        yield
    }
}
var x= mes();
</script>
function* mes(){
    var arr = ['第一句','第二句','第三句','第四句'];
    for(let i=0;i<arr.length;i++){
        console.log(arr[i]);
        yield
    }
}
var x = mec();
x.next();//每次调用next()方法执行,结果Object { value: undefined, done: false },前几次done都是false,最后一次为true

特点:对状态进行保存
④函数构造器 不推荐使用此方法

//前几个为函数的参数,后一个字符串为函数体
var adder = new Function('a', 'b', 'return a + b');
adder(2, 6);
//等价于:
function (a,b){
  return a+b;
}

问题一:写起来非常复杂
问题二:函数体的代码以字符串的形式传递给函数,js解释器执行函数时,要把字符串转换成可执行的代码,而转换成可执行的代码这个过程,在js的解释器中是调用了eval()函数,对数据和性能会造成很大影响,不建议使用
问题三:不能访问当前作用域,是在全局环境下创建的

几种创建函数方法总结:
1、只是创建函数,后续调用;建议使用函数声明语句创建函数,建议先声明,后调用
2、给对象的某个属性赋值,赋值为函数,简单来说就是给对象创建一个方法时,建议使用函数表达式;在回调函数中,需要使用函数表达式(因为函数表达式为匿名函数)
3、当你调试时,可以使用命名函数表达式协助;当时用递归时,也可使用命名函数表达式
4、如果需要对状态进行保存,可以使用此方法

备注:本内容学习总结来源于喜马拉雅冰山工作室沙翼老师主讲的(陪你读书(JavaScript WEB前端))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值