网站开发用php还是.net好,学网站开发哪个好,湖南网站设计制作,wordpress转发分享插件js的函数是对象#xff0c;可以通过程序来操控。比如#xff0c;可以把函数赋值给变量#xff0c;然后再传递给其他函数#xff0c;也可以在函数上设置属性#xff0c;甚至调用函数的方法。
js函数可以嵌套定义在其他函数里#xff0c;内嵌函数可以访问定义在函数作用域… js的函数是对象可以通过程序来操控。比如可以把函数赋值给变量然后再传递给其他函数也可以在函数上设置属性甚至调用函数的方法。
js函数可以嵌套定义在其他函数里内嵌函数可以访问定义在函数作用域的任何变量。这意味着js函数是闭包基于闭包可以实现重要且强大的编程技巧。
1 定义函数
function关键字可以用作函数声明或表达式。ES6定义了“箭头函数”语法特别简洁很适合把函数作为参数传给另一个函数。
1.1 函数声明
例如 function fun(x,y) {}
1函数的名字变成了一个变量这个变量的值就是函数本身。
2函数声明语句会被“提升”到包含脚本、函数或代码块的顶部因此调用代码可以出现在函数定义代码之前。
1.2 函数表达式
很像函数声明但函数表达式出现在复杂表达式或语句的上下文中而且函数名是可选的。例如
cosnt fun1 function(x) { return x 1; };
// 函数表达式可以包含名字这对递归有用。
const fun2 function fun(x) { if (x 1) return 1; else return fun(x-1); };
// 可以作为其他函数的参数
[1,2,3].sort(function(a,b) { return a-b; });
// 可以定义完立即调用
let resutl (function(x) { return x * x; }(10)); // result 100
表达式函数不能在它们定义之前被调用。
1.3 箭头函数
ES6中定义的一般形式是圆括号中逗号分隔的参数列表后跟箭头再跟包含在花括号中的函数体,例如
(x,y) { return xy; }
// 函数体中只有一个return语句时可以省略return关键字、语句末尾的分号以及花括号
(x,y) xy
// 只有一个参数时也可省略包围参数列表的圆括号
x x * x
// 对于没有参数的箭头函数则必须把空圆括号写出来
() 37
箭头函数相比于其他方式定义的函数有关极其重要的区别箭头函数从定义自己的环境继承this值。而不想其他方式定义的函数从调用上下文继承this值。而且箭头函数没有prototype属性。
2 调用函数
js函数可以通过5种方式来调用1作为函数2作为方法3作为构造函数4通过call()或apply()方法间接调用5通过js语言特性隐式调用。 函数调用 对于非严格模式下的函数调用this值是全局对象。但在严格模式下this值是undefined。 方法调用 this值是调用它的对象。 箭头函数 总是继承自身定义所在环境的this值。
表 函数调用、方法调用及箭头函数的this值
隐式函数调用对象属性的设置或获取方法、代理对象等。
2.1 构造函数调用
如果函数或方法调用前面加了一个关键字那它就是构造函数调用。
例如let o new Object();
与常规函数的区别在于参数处理、调用上下文(this)和返回值。
构造函数调用会创建一个新的空对象这个对象继承构造函数的prototype属性指定的对象。新创建的对象会被复制到这个函数的this中。例如
let obj new o.m(); 在方法m中this值是这个被创建的对象而不是o。
构造函数正常情况下不使用return关键字但是如果构造器函数显式使用啦return语句返回某个对象那么这个对象就会变成调用表达式的值。如果没有使用return 或者 return 的是一个原始值则这个返回值会被忽略仍然以新创建的对象作为调用表达式的值。
3 函数作为值
js 中函数是一个对象。
function fun() {}; //定义一个fun函数fun是引用函数对象的一个变量名。
let o {fun: function() {}}; //把函数赋值给对象的属性
3.1 定义函数自己的属性
如果一个函数需要一个“静态”变量且这个变量的值需要在函数每次调用时都能访问到则通常把这个变量定义为函数自身的一个属性。例如
fun.counter 0;
function fun() { return fun.counter; }
fun(); // 0
fun(); // 1
4 闭包
js使用词法作用域这意味着函数执行时使用的是定义函数时生效的变量作用域而不是调用函数时生效的变量作用域。js函数对象内部不仅要包括函数代码还要包括对函数定义所在作用域的引用。这种函数对象与作用域即一组变量绑定组合起来解析函数变量的机制被称作闭包。
4.1 闭包的作用
闭包真正值得关注的时候是定义函数与调用函数的作用域不同的时候。
最常见的情形是一个函数返回了在它内部定义的嵌套函数。
let scope global;
function fun() {
let scope fun-local;
return function() { return scope }
}。
console.log(fun()()); //fun-local
闭包的本质是它们会捕获自身定义所在外部函数的局部变量绑定。
let addFun ( function () {
let count 0;
return function () { return count; };
}());
console.log(addFun()); // 0
console.log(addFun()); // 1
在上面代码中不能通过其他方式直接操作count变量只能通过addFun这个函数。这样就实现了一个通用的共享私有状态的函数。
4.2 var 和 let 作用域问题
function fun() {
let funArr [];
for (var i 0; i 3; i) {
funArr[i] () i;
}
return funArr
}
let funArr fun();
console.log(funArr[0]()); // 3
console.log(funArr[1]()) ; // 3
console.log(funArr[2]()); // 3
这跟我们预期结果不同预期结果是1、2、3 而不是全都是3。这是因为var作用域提升到了fun()函数顶部而不是只局限于1次循环而且与闭包关联的作用域是“活的”所以在for循环中修改了i的变量值最后值变为3在后续调用中都共同访问了i这个变量所以返回的值都是3。
ES6增加了块级作用域变量解决了这个问题只要把var替换成let或者const。
function fun() {
let funArr [];
for (let i 0; i 3; i) {
funArr[i] () i;
}
return funArr
} l
et funArr fun();
console.log(funArr[0]()); // 0
console.log(funArr[1]()); // 1
console.log(funArr[2]()); // 2
let 和const是块级作用域的标志这意味着每一次循环都会定义一个与其他循环不同的独立作用域而每个作用域中都有自己独立的i绑定。
5 函数属性、方法和构造函数
5.1 call()和apply()方法
运行间接调用一个函数就像这个函数是某个其他对象的方法一样。第一个参数是要在其上调用这个函数的对象也就是函数的上下文(this)。
function fun() { console.log(this) }
let obj { name: ‘obj’}
fun.call(obj);
其中fun.call(obj);的作用相当于
obj.m fun;
obj.m();
delete obj.m;
如果箭头函数调用call()及apply()方法则第一个参数实际上会被忽略。
除了第一个参数后续所有参数都会传给被调用的函数,apply()方法与call()方法类似,只不过要传给函数的参数需要以数组的形式提供例如
function fun(x,y,z) {};
let obj {};
fun.call(obj,1,2,3); //等价于fun.apply(obj,[1,2,3])
5.2 bind()方法
把函数绑定到对象上bind()方法第一个参数是要绑定的对象。这个方法会绑定一个新的函数如果作为函数来调用这个新函数就会像f是绑定对象的方法一样调用原始函数。
function fun() { console.log(this.x) }
let obj {x:3};
let newFun fun.bind(obj)
newFun(); // 3
console.log(obj); // { x: 3 },注意bind()方法并不会改变该对象的结构即obj实际上是没有fun这个方法
let obj2 {x:4, newFun}; obj2.newFun(); // 3, 仍然是像fun是obj上的方法一样即始终是obj调用了fun
注意箭头函数调用了bind方法绑定不会起作用。
5.2.1 绑定部分应用
bind()方法也可以执行“部分应用”即在第一个参数之后传给bind()的参数也会随着this值一起被绑定。
let sum (x,y) x y;
let fun1 sum.bind(null,3)
console.log(fun1(2,4)); // 5. sum函数中x已被绑定fun1()形参只有一个y
5.3 Function()构造函数
const f new Function(“x”,”y”,”return xy;”); 相当于
const f function(x,y) { return xy; };
最后一个参数是函数体文本可以包含任意js语句相互以分号分隔。其他参数是新函数的参数名。
Function()构造函数的主要作用是动态创建和编译函数。
Function()创建的函数不使用词法作用域而是始终编译为如同顶级函数一样。
let scope global;
function fun() {
let scope fun-local;
return new Function(console.log(scope));
} fun()(); // 报错 scope is not defined
不要在Function构造函数的参数文本中读取该参数文本以外的变量。