//方式1:函数声明
function func () {}
//方式2:函数表达式
var func = function () {}
//方式3
var func=new Function()//es6
var sum = new Function(‘a‘, ‘b‘, ‘return a + b‘);
console.log( sum(1, 2) ); // 3
// 带参数的函数声明
function 函数名(形参1, 形参2, 形参...){
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3);
函数的调用方式决定了 this
指向的不同:
调用方式 | 指向(非严格模式) | 备注 |
---|---|---|
普通函数调用 | window | 严格模式下是 undefined |
构造函数调用 | 实例对象 | 原型方法中 this 也是实例对象 |
对象方法调用 | 该方法所属对象 | |
事件绑定方法 | 绑定事件对象 | |
定时器函数 | window |
var name=‘HJJ‘;
var obj = {
name:"HHH",
age:18,
myFun:function(){
console.log(this)
console.log(this.name+‘年龄‘+this.age);
}
}
obj.myFun(); //HHH年龄18 ===>对象方法调用,this是该对象obj
var result=obj.myFun; //==>result=myFun,普通函数,this是window
result();//HJJ年龄undefined
result.call(obj);//HHH年龄18 ===>call改变this指向,this是obj....即result添加到obj环境中
result.apply(obj);//HHH年龄18 ===>apply改变this指向,this是obj
result.bind(obj)();//HHH年龄18 ===>bind改变this指向,this是obj
call()、apply()、bind() 方法的共同点和区别:
作用:都是用来改变函数的this对象的指向的。
语法:
call(thisObj,value1,value2...)
apply(thisObj,[value1,value2...])
bind(thisObj,value1,value2...)
参数:
返回值:
var person1 = {
name:"HHH",
age:18,
myFun:function(height,job){
this.height=height
console.log(this)
console.log(this.name+‘年龄‘+this.age+‘身高‘+height+‘工作‘+job);
}
}
var person2 = {
name:"LLL",
age:99
}
person1.myFun.call(person2,168,‘actor‘)//LLL年龄99身高168工作actor。。。即person1.myFun添加到person2环境中
person1.myFun.apply(person2,[168,‘actor‘])//LLL年龄99身高168工作actor
person1.myFun.bind(person2,[168,‘actor‘])()//LLL年龄99身高168工作actor
arguments对象:存储了传递的所有的实参。不是一个数组,arguments是一个伪数组,可以进行遍历。
arguments[index]:实参集合
length:实参的个数
callee:引用函数本身
caller:函数的调用者
length:形参的个数
name:函数的名称
function func1(x, y) {
console.log(func1.length) // 2 ==>形参的个数
console.log(func1.name) //func1 ==> 函数的名字
console.log(func1.caller) //函数的调用者
console.log(arguments) // [10, 20, 30, callee: ?, Symbol(Symbol.iterator): ?]
//不需要明确指出参数名,就能访问每个实参。
console.log(arguments[0]);//10
console.log(arguments[1]);//20
console.log(arguments[2]);//30
console.log(arguments.length);//2==>实参的个数
console.log(arguments.callee)//函数本身
console.log(arguments.callee === func1) //true==>函数本身
console.log(arguments instanceof Array) //false==>w
}
function func2() {
func1(10, 20, 30)
console.log(func2.caller) //null
}
func2()
var sum = function (n) {
if (1 == n) {
return 1;
} else {
return n + arguments.callee(n - 1);
}
}
console.log(sum(6));//21
(function (str) {
console.log(123+str);
})(‘hello‘);
//123hello
var func = (function () {
var init = function () {
...
};
return {
init: init
}
}());
func.init();
1、外部访问函数内部变量
function func1(){
var n=999;
function func2(){
console.log(n)
}
return func2;
}
var result=func1();//===>转换: result=func2
result(); // 999 ===>转换:func2()
/**
func2可以访问func1内部的所有局部变量。
想要外部读取func1的内部变量,可把func2作为返回值。
**/
2、局部变量会常驻在内存中
function func1(){
var n=1;
var b=2;
function func2(){
n++
console.log(n,b)
}
function func3(){
b+=2;
}
}
func3();
return func2,
}
var result=func1();//===>转换: result=func2
result(); // 2,4 ===>转换:func2()
result(); // 3,4 ===>转换:func2()
3、可以避免使用全局变量,防止全局变量污染
4、缺点:会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
var result=(function(){
var n=1;
function func2(){
n++
console.log(n)
}
function clearVariable(){
n=null
}
return {
func2:func2,
clearVariable:clearVariable
}
})()
result.func2(); // 2
result.func2(); // 3
result.clearVariable();//清除变量
result.func2(); // 1
//阶乘的递归
function factorial (num) {
if (num <= 1) {
return 1
} else {
//return num * arguments.callee(num - 1)
return num * factorial(num - 1)
}
}
factorial(5)//120
//注:必须要有结束递归的条件
应用场景:深拷贝、菜单树、遍历 DOM 树
重载:相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。
覆盖(也叫重写):函数名和参数都一样,只是函数的实现体不一样。一般用于子类覆盖父类的方法。
//重载
function add(n1,n2){
console.log(n1+n2);
}
function add(n1,n2,n3){
console.log(n1+n2+n3);
}
add(1,2);//NaN
add(1,2,3);//6
//重写
function text(){
console.log(‘text1‘);
}
function text(){
console.log(‘text2‘);
}
text();//"text2"
function fn(){
switch(arguments.length){
case 0:
addFn(arguments.length)
break
case 1:
deleteFn(arguments.length)
}
}
function addFn(n){
console.log(n++)
}
function deleteFn(n){
console.log(n--)
}
fn() // 1
fn(1) // 0
原文:https://www.cnblogs.com/jiajia-hjj/p/15219980.html