首先先熟悉下语法,先写一个函数其实和swift中写函数是很像的
function sum(num1,num2)
{
return num1+num2;
}
var result = sum(2,3);
console.log(result);
接下来引入下匿名函数的概念,匿名函数我们创建起来之后如果我们不去定义一个变量去接收,我们肯定是无法使用的,所以我们下面就去定义一个res去接收,然后去调用,匿名函数其实就相当于是OC中的block也就是Swift的闭包。
//匿名函数
var res = function(){
console.log("hello world");
}
res();
我们当然可以把这个匿名函数当做参数传入到一个方法中
function funct(block)
{
block();
}
funct(res);
之后我们再去看看JS中的闭包指的是把在一个函数中去创建另一个函数
//JS中的闭包,这里其实也就是相当于block作为返回值
function func1(num1)
{
return function(num2)
{
return num1+num2;
}
}
var temp = func1(4);
var temp1 = temp(5);
console.log(temp1);
这里再介绍下作用域的概念,如果我们外面声明一个变量在代码块中也定义了一个同名变量,这个同名变量会覆盖外面的变量,比如说下面这个例子最后打印出来的string1变成了是world,因为在JS中是没有块级作用域的,只有函数作用域。
var string1 ='hello'
if(true)
{
var string1='world';
}
console.log(string1);
如果是在函数中声明了一个同名的变量,而外面有一个同名的全局变量,那么输出的就是那个全局变量的值,也就是说这里输出的是hello
var string1 ='hello'
function test(){
var string1='kkll';
}
test();
console.log(string1);
还有就是如果在函数的作用域中就比如说上面我们没用var来声明变量而是直接使用了string1那么修改的就是外面的那个同名的全局变量。以及在JS中没有用var声明的变量都是全局变量
再简单的介绍下用let修饰的变量和用var修饰的变量
let 允许把变量的作用域限制在块级域中。而用var定义变量要么是全局的,要么是函数级的,不能是块级的,而且在for循环中用for(var i=0;i<10;i++)这样var所定义的变量,地址是不会进行改变的。不管循环多少次。
function test() {
let x = 20;
if (true) {
let x = 10; // 两者是不同的变量
console.log(x); // 10
}
console.log(x); // 20
}
以及我们去给li标签设置鼠标移动上去的效果的时候,如果直接去打印i的话打印出来的都是5,因为i是函数级的变量,最后执行完成就是5,所以内部的函数也都是指向它的,但如果我们定义了一个let变量,它的作用域是块级的打印出来的就是我们设置的标号了,用 let 定义的变量的作用域是定义它们的块内,以及包含在这个块中的子块
下面这里就是,每一次循环的k其实都是一个新的变量,在它的子块内去引用了它,js就会把它作为函数的上下文保存起来。
//遍历
for(var i=0;i<lis.length;i++)
{
var li = lis[i];
let k = i
li.onmouseover = function (){
console.log(k)
//this,这里面的this指的就是function这个函数的调用者,这个函数的所属者
}
}
打印如下
当然如果我们这么写也是可以的,也能打印出不同的i出来,这个里面的k代表的就是i。那么为什么可以打印出来?那是因为
变量i传到一个闭包里,变成了局部变量i,这个局部变量的作用域内有了一个闭包函数去引用了它,js就会把它作为这个函数的上下文保存起来,function()这个括号里面的参数的名字我们可以随便取,但是最后的那个括号(i)是一定要传入i的,毕竟要在里面做操作。
for(var i=0;i<lis.length;i++)
{
var li = lis[i];
li.onmouseover = (function(i){
return function () {
console.log("Item " + i + " is clicked.");
}
})(i);
}