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是传入的函数作为参数. 其实高阶函数用的很多.其实平 ...
随机推荐
- org.hibernate.hql.ast.QuerySyntaxException: tb_voteoption is not mapped [from tb_voteoption where voteID=?]
转自:https://www.cnblogs.com/albert1017/archive/2012/08/25/2656873.html org.hibernate.hql.ast.QuerySyn ...
- HTTPS证书转换成PEM格式
PEM 格式的证书文件(*.pem)一般为以下格式: 注意:PEM 格式证书文件可用 notepad++ 等文本编辑器打开. CER / CRT 格式证书转换为 PEM 格式 对于 CER / CRT ...
- 2019-4-21-Roslyn-通过-NuGet-库修改应用程序入口函数
title author date CreateTime categories Roslyn 通过 NuGet 库修改应用程序入口函数 lindexi 2019-4-21 17:37:1 +0800 ...
- Linux下安装Dubbox
1.Dubbox简介 Dubbox 是一个分布式服务框架,其前身是阿里巴巴开源项目Dubbo ,被国内电商及互联网项目中使用,后期阿里巴巴停止了该项目的维护,当当网便在Dubbo基础上进行优化,并继续 ...
- 【rabbitmq】解决SimpleAmqpClient创建连接时阻塞的问题
https://blog.csdn.net/panxianzhan/article/details/50755409 https://blog.csdn.net/csm201314/article/d ...
- Tenka1 Programmer Contest D - Crossing
链接 Tenka1 Programmer Contest D - Crossing 给定\(n\),要求构造\(k\)个集合\({S_k}\),使得\(1\)到\(n\)中每个元素均在集合中出现两次, ...
- 测试tensorflowgpu版本是否可用
输入一下代码即可 import tensorflow as tf print(tf.test.is_gpu_available())
- java File过滤文件的多种方法
package com.qf.part1; import java.io.File; import java.io.FileFilter; import java.io.IOException; pu ...
- re正则常用示例积累
2019-12-7 import re ''' 示例1: 提取网站的网址 ''' urls = ['https://blog.csdn.net/xxcupid/article/details/5199 ...
- Redis使用场景一,查询出的数据保存到Redis中,下次查询的时候直接从Redis中拿到数据。不用和数据库进行交互。
maven使用: <!--redis jar包--> <dependency> <groupId>redis.clients</groupId> < ...