07 (H5*) js课程第8天 高阶函数、闭包、沙箱
目录:
1:call和apply方法调用
2:bind方法复制
3:函数中的几个属性值
4:高阶函数,函数作为参数
5:高阶函数,函数作为返回值。
6: 作用域链,作用域,预解析
7:闭包--延长作用域链
8: 沙箱:测试,虚拟环境
1:call和apply方法调用
<script>
function f1 (x, y) {
console.log("结果是:"+(x+ y) + this);
} // 函数的调用
f1(10, 20); console.log("==========="); //1: 此时的f1实际上是当成对象来使用的,对象可以调用方法,apply和call方法也是函数的调用的方式 f1.apply();
f1.call(); //2: apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的, apply传入的是数组, call,传入的是参数 f1.apply(null, [100, 200]); f1.call(null, 100, 200);
console.log("==========="); function f2(x, y){
console.log("这个函数是window对象的一个方法"+ (x+y) + this);
console.dir(this);
} window.f2(10, 20); var obj = {
age: 10,
name: "张三",
} //3: apply和call可以改变this的指向,
window.f2.call(obj, 10, 20);
window.f2.apply(obj, [10,20]); // 4:apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype,原型对象中。
原型对象可以看成+方法,实例方法可以当成-方法。调用+方法时候可以当成对象。
console.log(f2.__proto__ == Function.prototype); console.log(Function.prototype); //{ [native code] } console.dir(Function); </script>
2:bind方法复制
<script>
console.log("===== 11 =====")
function f1 (x, y ){
console.log((x+y) + " :======>>>>"+this );
console.dir(this);
}
f1.bind();
// 方法复制了一份,并且传递参数,结果还是方法,方法没有调用。此时f1是对象。
// bind方法是复制的意思,可以在复制的时候传递参数,也可以在复制之后传递参数
// apply 和 call 是调用的时候改变this的指向
// bind是 复制的时候修改this的指向
var ff = f1.bind(null, 10, 20);
console.log (ff);
ff();
var f2 = f1.bind(null);
f2(10, 20);
console.log("===== 22 =====")
// bind是方法复制,apply和call是方法调用
function Person (){
this.age = 10;
}
Person.prototype.eat = function () {
console.log("这个是吃");
};
var per = new Person;
var ff = f1.bind(per);
ff(10, 20);
console.log("===== 33 =====")
function Person(age) {
this.age = age;
}
Person.prototype.play = function () {
console.log(this + "========>>>>" + this.age);
}
function Student (age) {
this.age = age;
}
var per = new Person(10);
var stu = new Student(20);
var paly2 = per.play.bind(stu);
paly2();
</script>
3: 函数中几个属性
<script>
//函数中有一个name属性----->函数的名字,name属性是只读的,不能修改
//函数中有一个arguments属性--->实参的个数
//函数中有一个length属性---->函数定义的时候形参的个数
//函数中有一个caller属性---->调用(f1函数在f2函数中调用的,所以,此时调用者就是f2)
function f1(x,y) {
console.log(f1.name);
console.log(f1.arguments.length);
console.log(f1.length);
console.log(f1.caller);//调用者
}
f1.name="f5";
f1(10,20,30,40);
console.dir(f1); function f2() {
console.log("f2函数的代码");
f1(1,2);
}
f2();
</script>
4:高阶函数之参数是函数
<script>
//fn是参数,最后作为函数使用了,函数是可以作为参数使用
function f1(fn) {
console.log("f1的函数");
fn();//此时fn当成是一个函数来使用的
}
//1: 传入匿名函数
f1(function () {
console.log("我是匿名函数");
});
console.log("======= 22 ========");
// 命名函数
function f2() {
console.log("f2的函数");
}
// 2:传入的是命名函数
f1(f2);
//函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号
</script>
5: 函数作为返回值
<script>
console.log("======== 11 =========");
function f1() {
console.log("f1函数的开始");
return function () {
console.log("我是函数,但是我是我是我为函数的返回值");
};
// 我是不会执行的,因为此行代码上面有return
console.log("f1函数的结束");
}
var f2 = f1();
f2();
console.log("======== 22 =========");
var num=10;
console.log(typeof num);//获取num这个变量的数据类型
var obj={};//对象
//判断这个对象是不是某个类型的
console.log(obj instanceof Object);
//获取某个对象的数据类型的样子
//Object.prototype.toString.call(对象);//此时得到的就是这个对象的类型的样子
//此时输出的是Object的数据类型 [object Object]
console.log(Object.prototype.toString());
//输出的数组的数据类型 [object Array]
console.log(Object.prototype.toString.call([]));
var arr=[10,20,30];
console.log(Object.prototype.toString.call(arr));
console.log("======== 33 =========");
//获取某个对象的类型是不是你传入的类型
//[10,20,30] 是不是"[object Array]"
//type---是变量----是参数----"[object Array]"
//obj---是变量-----是参数----[10,20,30];
//判断这个对象和传入的类型是不是同一个类型
function getFunc(type) {
return function (obj) {
return Object.prototype.toString.call(obj) === type;
}
}
var ff = getFunc("[object Array]");
var result = ff([10, 20, 30]);
console.log(result);
var ff1 = getFunc("[object Object]");
var dt = new Date();
var result1 = ff1(dt);
console.log(result1);
</script>
6:作用域,作用域链,预解析
1:局部变量。函数中的变量是局部变量,外边无法访问。
2:预解析:变量的声明,和函数的声明提前
<script>
// 变量---->局部变量和全局变量,
// 作用域:就是变量的使用范围
// 局部作用域和全局作用域
// js中没有块级作用域---一对括号中定义的变量,这个变量可以在大括号外面使用
// 函数中定义的变量是局部变量
while(true){
var num=10;
break;
}
console.log(num);
{
var num2=100;
}
console.log(num2);
if(true){
var num3=1000;
}
console.log(num3);
function f1() {
//局部变量
var num1=10;
}
// console.log(num1);
console.log("======== 22 ======");
// 作用域链:变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了
// 层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错
var num=10; //作用域链 级别:0
var num2=20;
var str = "abc"
function f1() {
var num2=20;
function f2() {
var num3=30;
console.log(num);
}
f2();
}
f1();
//预解析:就是在浏览器解析代码之前,把变量的声明和函数的声明提前(提升)到该作用域的最上面
//变量的提升
console.log(num);
var num=100;
//函数的声明被提前了
f1();
function f1() {
console.log("这个函数,执行了");
}
var f2;
f2=function () {
console.log("小杨好帅哦");
};
f2();
</script>
7:闭包
1:闭包的定义:
函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。
<script>
/* 闭包
* 闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。 *闭包的模式:函数闭包和对象闭包 * 闭包的作用:缓存数据,延长作用域链 * 闭包的优点和缺点:缓存数据 * 闭包的应用: * ****/ console.log("======= 11 ========");
// 1:函数式闭包
function f1() {
var num = 10; // 函数
function f2() {
console.log(num);
} f2();
} f1(); console.log("======= 22 ========");
// 2:对象是闭包
function f3() { var num1 = 20; // 对象
var obj = {
age : num1,
} console.log(obj.age);
} f3(); console.log("======= 33 ========"); function f4() {
var num4 = 40;
return function () {
console.log(num4);
return num4;
};
} var ff1 = f4();
var result = ff1();
console.log(result); console.log("======= 44 ========");
function f5() {
var num5 = 50;
var obj = {
age : num5,
}
return obj;
} var resultObj = f5();
var result5 = resultObj.age;
console.log(result5);
</script>
2:闭包的例子
<script>
console.log("======= 11 =========");
function f1 () {
var num = 10;
num ++ ;
console.log(num);
}
f1(); // 11
f1(); // 11
f1(); // 11
console.log("======= 22 =========");
// 闭包缓存数据
// 总结:如果想要缓存数据,需要把数据放在外层函数和内层函数之间。
// 闭包的作用:缓存数据。优点也是缺点,没有及时释放
// 局部变量在函数中,函数使用结束后,局部变量就会被自动释放。
// 闭包后,里面的局部变量的使用作用域链就会被延长。
function f2() {
var num = 20;
return function () {
num ++;
return num;
};
}
var ff1 = f2();
console.log(ff1()); // 21
console.log(ff1()); // 22
console.log(ff1()); // 23
console.log("======= 33 =========");
// 产生3次相同的随机数
//
function f3() {
var num3 = parseInt(Math.random()*10+1);
return function () {
console.log(num3);
}
}
var ff3 = f3();
ff3();
ff3();
ff3();
</script>
8:沙箱:虚拟测试和真实世界结果一样,不影响真实世界。
1:沙箱的定义和2中格式
<script>
//沙箱:环境,黑盒,在一个虚拟的环境中模拟真实世界,做实验,实验结果和真实世界的结果是一样,但是不会影响真实世界 // 沙箱 函数的自调用 console.log("======== 11 ========");
// 沙箱的模板,函数自调用两种格式
// 格式一: ()();
(function () {
var num = 10;
console.log(num + 10);
})(); // 格式二:使用的比较多. (());
(function () {
var num = 10;
console.log(num + 20);
}()); </script>
9:递归
1:定义:自己调用自己一定 要有结束条件。
<script>
console.log("======= 11 =======");
// 求n个数的和
// 倒序递归,结束条件 5+4+3+2+1
function getSum(n) {
// 结束条件
if(n ==1){
return 1;
}
return n + getSum(n - 1);
}
console.log(getSum (5));
/*
*
* 执行过程:
* 代码执行getSum(5)--->进入函数,此时的x是5,执行的是5+getSum(4),此时代码等待
* 此时5+getSum(4),代码先不进行计算,先执行getSum(4),进入函数,执行的是4+getSum(3),等待, 先执行的是getSum(3),进入函数,执行3+getSum(2),等待,先执行getSum(2),进入函数,执行 2+getSum(1);等待, 先执行getSum(1),执行的是x==1的判断,return 1,所以,
* 此时getSum(1)的结果是1,开始向外走出去
* 2+getSum(1) 此时的结果是:2+1
* 执行:
* getSum(2)---->2+1
* 3+getSum(2) 此时的结果是3+2+1
* 4+getSum(3) 此时的结果是4+3+2+1
* 5+getSum(4) 此时的结果是5+4+3+2+1
*
* 结果:15
*
* */
</script>
注意:
07 (H5*) js课程第8天 高阶函数、闭包、沙箱的更多相关文章
- js 高阶函数 闭包
摘自 https://www.cnblogs.com/bobodeboke/p/5594647.html 建议结合另外一篇关于闭包的文章一起阅读:http://www.cnblogs.com/bob ...
- Python高阶函数-闭包
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 在这里我们首先回忆一下python代码运行的时候遇到函数是怎么做的. 从python解释器开始执行之后,就在内存中开辟了一个空间 每当 ...
- 浅谈JS高阶函数
引入 我们都知道函数是被设计为执行特定任务的代码块,会在某代码调用它时被执行,获得返回值或者实现其他功能.函数有函数名和参数,而函数参数是当调用函数接收的真实的值. 今天要说的高阶函数的英文为High ...
- Javascript 闭包与高阶函数 ( 一 )
上个月,淡丶无欲 让我写一期关于 闭包 的随笔,其实惭愧,我对闭包也是略知一二 ,不能给出一个很好的解释,担心自己讲不出个所以然来. 所以带着学习的目的来写一写,如有错误,忘不吝赐教 . 为什么要有闭 ...
- Java函数式编程:二、高阶函数,闭包,函数组合以及柯里化
承接上文:Java函数式编程:一.函数式接口,lambda表达式和方法引用 这次来聊聊函数式编程中其他的几个比较重要的概念和技术,从而使得我们能更深刻的掌握Java中的函数式编程. 本篇博客主要聊聊以 ...
- js高阶函数应用—函数防抖和节流
高阶函数指的是至少满足下列两个条件之一的函数: 1. 函数可以作为参数被传递:2.函数可以作为返回值输出: javaScript中的函数显然具备高级函数的特征,这使得函数运用更灵活,作为学习js必定会 ...
- js高阶函数
我是一个对js还不是很精通的选手: 关于高阶函数详细的解释 一个高阶函数需要满足的条件(任选其一即可) 1:函数可以作为参数被传递 2:函数可以作为返回值输出 吧函数作为参数传递,这代表我们可以抽离一 ...
- [Node.js] 闭包和高阶函数
原文地址:http://www.moye.me/2014/12/29/closure_higher-order-function/ 引子 最近发现一个问题:一部分写JS的人,其实对于函数式编程的概念并 ...
- 【js】高阶函数是个什么?
所谓高阶函数,就是函数中可以传入另一个函数作为参数的函数. 简单一张图,方便理解全文. function 高阶函数(函数){} 这是一个高阶函数,f是传入的函数作为参数. 其实高阶函数用的很多.其实平 ...
随机推荐
- C# System.Web.Caching.Cache类 缓存 各种缓存依赖
原文:https://www.cnblogs.com/kissdodog/archive/2013/05/07/3064895.html Cache类,是一个用于缓存常用信息的类.HttpRuntim ...
- sqoop简单使用
一,通过sqoop将MySQL里面的数据加载到HDFS 先查看有哪些数据库 查看表person sqoop list-databases --connect jdbc:mysql://ly-p2p4: ...
- Vue实现active点击切换
Vue实现active点击切换 循环的情况: 1.点击时传入index索引(获取当前点击的是哪个) @click=“active(index)” 2.将索引值传入class(索引等于几就第几个添加ac ...
- vim ctags
ctags -I __THROW -I __attribute_pure__ -I __nonnull -I __attribute__ --file-scope=yes --langmap=c:+. ...
- 字符串format函数使用
#format拼接字符串,format()内的参数必须为可迭代的对象p1="i am {2},age {1},{0}".format("seven",18,'a ...
- java并发学习--第一章 线程的创建
所谓的并发就是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行.所以我们看似几个线程在同时进行,其实在操作系统中 ...
- ThinkPhp view 路径用到的常量 __STATIC__ __JS__ __CSS__等
https://www.edoou.com/articles/1556848583530922 ThinkPHP5.1 里面__PUBLIC__无法生效的问题 在用PHP模板的时候需要引用外部的样式文 ...
- python数据分析第二版:数据加载,存储和格式
一:读取数据的函数 1.读取csv文件 import numpy as np import pandas as pd data = pd.read_csv("C:\\Users\\Admin ...
- HTTP通信安全和Web攻击技术
一.HTTPS,确保Web安全 在HTTP协议中可能存在信息窃听或身份伪装等安全问题,HTTP的不足: 通信使用明文(不加密),内容可能会被窃听 不验证通信方的身份,因此有可能遭遇伪装 无法证明报文 ...
- [JSOI2004]平衡点 / 吊打XXX 题解
预备概念: 金属退火:将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却 温度:一个逐渐减小的参数,表示接受次优解的概率 模拟退火是一种解决复杂问题的算法,相当于贪心,但以一个逐渐减小的该率接 ...