JavaScript函数
函数:就是一个可以反复执行的代码块
为什么使用函数:
- 您能够对代码进行复用:只要定义一次代码,就可以多次使用它。
- 您能够多次向同一函数传递不同的参数,以产生不同的结果。
创建一个函数:
- 函数创建的过程,就是找一个堆内存空间,把函数代码放进去,把内存地址赋值给函数名
function 函数名(){ //函数体 }
函数名() //函数调用
调用函数:
- 函数声明之后可以多次调用;
- 函数每次调用都会产生一个新的所有作用域,作用域之间的变量无法互相访问,全局作用域也不能访问私有作用域中的变量;
-
- 当事件发生时(当用户点击按钮时)
- 当 JavaScript 代码调用时
- 自动的(自调用)
函数返回值:
- 函数执行之后想留下返回值,就需要使用return返回一个值;
- 如果没有使用return,函数留下的是undefined(函数返回值默认是undefined)
- return可以终止函数体代码的执行
function sum(){ var total = 1+3; return total; //返回的是total代表的值 console.log(total);//这个代码不会运行 } var n = sum(); //n = 4
函数参数:
- 函数参数为函数实现了更加灵活的功能
- 形参未赋值,默认值为undefined
function sum(n,m){ //函数定义同时定义形参,相当于声明了两个变量 var total = n+m; return total; } var t = sum(100,200);//调用函数时传递实参 console.log(t);
封装获取元素样式的函数:
function getCss(ele,attr){ return ele.currentStyle==="undefined" ? getCoumputedStyle(ele)[attr] : ele.currentStyle[attr]; } getCss(box,'width');
arguments是函数中内置的一个对象,表示的是实参的集合:
function fn(){ console.log(arguments); } fn(1); //arguments [1] fn(1,2); // arguments [1,2]
函数的不用形式:
- 命名函数;
function sum(){ } sum();
- 事件处理函数;
//事件处理函数,一般使用的是匿名函数 box.onclick = function(){ } //如果事件绑定使用的是命名函数,不能加(),不能传参 box.onclick = fn; //如果命名函数需要传参,需要放在匿名函数里面 box.onclick = function(){ fn('hello'); }
- 函数作为对象的方法;
var obj = { name:'ujiuye', age:18, eat:function(){ //eat方法 console.log('吃面条!'); } } obj.eat();
函数中this的指向问题:
- 普通函数中this指向window对象;
//命名函数(普通函数) function fn(){ console.log(this);// 普通函数里面的this是window } fn();
- 事件处理函数中this指向触发事件的元素;
var oBox = document.getElementById('box'); //事件处理函数,一般使用的是匿名函数 oBox.onclick = function(){ console.log(this); // oBox }
- 对象的方法里边this指向调取方法的对象;
var obj = { name:'ujiuye', age:18, eat:function(){ //eat方法 console.log(this); } } obj.eat(); // obj
全局作用域&私有作用域:
- 全局作用域:js运行时浏览分配的栈空间(公共空间);
- 私有作用域:函数执行时会产生私有作用域;
全局变量&局部变量:
- 全局变量:在全局作用域声明的变量,叫做全局变量,再任何地方都可以访问,只要没有在函数中声明的变量都叫全局变量;
- 局部变量:在函数里声明的变量,或者函数的形参,都是局部变量,在作用域外不可以访问;
什么是作用域链?
函数中是使用变量,从当前作用域里开始查找,如果没有向上一级作用域查找,如果还没有会继续向上查找,直到查到全局作用域,如果还没有,就会报错。(子可以找父,父不可以找子)
什么是预解析(变量提声)?
- 浏览器在运行之前会先找到var ,function提前声明;
- 带var的声明不赋值,值暂时为undefined;
- 带function的声明并赋值;
- 预解析完毕才从上到下执行代码;
- 预解析发生在当前作用域,函数执行时也会先进行预解析,然后运行函数;
普通函数和表达式声明的函数有什么区别:
fn1();//因为函数在预解析时已经被声明并且赋值,所以可以在再函数定义之前调用 function fn1(){ } fn2(); // 因为函数写在等号后面不会被预解析,所以这种方式不能再函数定义之前调用 var fn2 = function(){ }