JavaScript的函数

  • JavaScript学习过程中的个人笔记,详细请看https://www.liaoxuefeng.com/wiki/1022910821149312
  • 再次感谢廖大
函数的定义
	//定义函数的方式一
	function abs(x){
		return x;
	}
	
	//方式二
	var abs = function(x){
		return x;
		};
	//方式二定义了一个匿名函数,没有函数名,但这个匿名函数复制给了变量abs,所以通过abs就可以调用该函数。
	//方式二需要在最后加上分号,以表示赋值语句结束
  • Js允许传入任意个参数而不影响调用。
  • Js有一个关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。类似一个Array但不是。
  • 通过arguments,即使函数不定义任何参数,还是可以拿到参数的值。
  • 实际上arguments最常用于判断传入参数的个数。
  • ES6引入了rest参数,用来获取除定义外的其他参数。
	function foo(a, b, ...rest){}
	//rest只能写在最后,前面用...标识。传入的多余的参数以数组的形式交给变量rest
	//如果传入的参数比正常的参数还少,那么rest参数会接受到一个空数组,而不是undefined。
变量
  • Js的函数中会先扫描整个函数体的语句,把所有声明的变量提升到函数顶部,但不会提升变量的赋值。
	'use strict'
	var x = 'Hello, ' + y;
	console.log(x);
	var y = 'Bob';
	//不会报错,但是会输出 Hello, undefined。
	//说明Js引擎自动提升了变量y的声明,但不会提升y的赋值。
  • 不在任何函数内定义的变量就具有全局作用域。实际上Js默认有一个全局对象window。全局作用域的变量实际上被绑定到window的一个属性。
名称空间
  • 全局变量会绑定到window上,不同的Js文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。
  • 减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。
	var MYAPP = {};//唯一的全局变量MYAPP

   //其他变量
   MYAPP.name = 'myapp';
   MYAPP.version = 1.0;

   //其他函数
   MYAPP.foo = function(){return 'foo'};
局部作用域
  • Js的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的。
  • ES6引入了关键字let,用let代替var可以什么一个块级作用域的变量。
常量
  • 要声明一个常量,在ES6前是不行的,我们通常用全部大写的变量来表示这是一个常量,不要修改它的值。
  • ES6引入了关键字const来定义常量,const和let都具有块级作用域。
解构赋值
  • ES6开始,JS引入了解构赋值,可以同时对一组变量进行赋值。
	'use strict';
	var [x, y, z] = ['hello', 'JavaScript', 'ES6'];

	let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];//嵌套数组解构赋值
	
	var [, , z] = ['hello', 'JavaScript', 'ES6'];//忽略前两个元素,只对z赋值第三个元素

	var person = {
		name:'小明',
		age:20,
		gender:'male',
		passport:'G-1234567',
		school:'No.4 middle school',
		address:{
				city:'beijing',
				zipcode:'10001;
				}
		};
	var  {name, age, passport, address:{city, zipcode}} = person;//快速获取对象的**指定属性**,
	//如果要使用的变量名和属性名不一致,可以使用下面的语法获取
    let {name, passport:id} = person;//把passport属性赋值给变量id,此处的passport不是变量,而是属性。

    //解构赋值也可以使用默认值,以避免不存在的属性返回undefined的问题。
    var {name, single = true} = person;//如果person对象没有single属性,默认赋值为true
  • 如果一个函数接受一个对象作为参数,那么可以使用解构直接把对象的属性绑定到变量中。
方法
  • 在一个对象中绑定函数,称为这个对象的方法。
  • 在一个方法内部,this始终指向当前对象。
  • Js的函数内部如果调用了this,那么这个this的指向视情况而定:
    1)如果以对象的方法形式调用,该函数的this指向被调用的对象
    2)如果单独调用函数,此时,此函数的this指向全局对象,也就是window。
  • 可以用函数本身的apply方法来指定函数的this指向哪个对象,它接收两个参数,第一个参数是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。
  • 还可以使用call方法,和apply的区别是,apply()把参数打包成Array传入,call()把参数按顺序传入。
高阶函数
  • Js的函数都指向某个变量。一个函数也可以接收另一个函数作为参数,这种函数就称之为高阶函数。
  • Array().map():创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
  • Array().reduce():这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算。
  • Array().filter():接收一个函数,将传入的函数依次作用于每个元素,然后根据返回值是true或false来决定保留或丢弃该元素。
  • Array().sort():排序方法,可以传入一个方法来进行自定义排序,默认的排序方法是暗示ASCII码排序,并不精确。
  • Array().every():判断数组的所有元素是否满足测试条件。
  • Array().find():用于查找符合条件的第一个元素,如果找到了返回这个元素,否则,返回undefined。
  • Array().findIndex():用于查找符合条件的第一个元素,如果找到了返回这个元素的索引,否则,返回-1;
  • Array().forEach():与map类似,把每个元素依次作用于传入的函数,但不会返回行的数组。常用于遍历数组,因此传入的函数不需要返回值。
闭包
  • 高阶函数出了可以接受函数作为参数外,还可以把函数作为结果值返回。
  • 返回函数不要引用任何循环变量,或者后续会发生变化的变量。
  • 如果一定要引用循环变量,可以再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。
  • 创建一个匿名函数并立即执行的语法:
	(function (x) { return x * x; })(3); //9
  • 借助闭包,可以用来封装私有变量。闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。
箭头函数
  • ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
  • 箭头函数相当于匿名函数,并且简化了函数定义。
  • 箭头函数有两种格式:
	//只包含一个表达式
     x => x * x; //相当于  function(x){return x * x;}
   
   //包含多条语句,这个时候就不能省略{}和return;
   x => {
   	if(x >0){
   		return x * x;
   	}
   	else {
   		return -x*x;
   	}
   }
   //如果不是一个参数,就需要用括号
   (x,y) => x * x + y * y; //两个参数

   () => 3.14;//无参数

   (x, y, ...rest) => {
   	var i, sum = x + y;
   	for(i = 0;i< rest.length;i++){
   		sum += rest[i];
   	}
   	return sum;
   }//可变参数
   	
   //如果要返回一个对象,如果是单表达式,则需要加个括号
   x => ({ foo:x })
  • 箭头函数和匿名函数有个明显的区别:箭头函数修复了this的指向,箭头函数内部的 this 是词法作用域,由上下文确定。
  • 由于this在箭头函数中已经按照词法作用域绑定了,所以用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略。
generator(生成器)
  • generator是ES6引入的新的数据类型,一个generator看上去像一个函数,但可以返回多次。
  • generator由function*定义,并且除了return语句,还可以用yield返回多次。
  • 调用generator对象有两种方法,
    1)不断调用generator对象的next()方法,这个方法每次遇到yield x 就会返回一个对象{value:x,done:true/false},然后暂停,返回的value就是yield的返回值,done表示这个generator是否已经执行结束了,如果done为true,则value就是return的返回值。
    2)直接用for…of循环迭代generator的对象,这种方式就不需要自己判断done。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值