一、函数的定义方式

 1.函数声明方式 function  关键字(命名函数)

 2.函数表达式(匿名函数)

 3.new  Function( )

 var  fn = new  Function(‘参数1’,‘参数2’.....,‘函数体’)

  • Function 里面参数都必须是字符串格式
  • 第三种方式执行效率低,也不方便书写,很少使用
  • 所有函数都是 Function 的实例(对象)
  • 函数也属于对象

二、 函数的调用方式

  // 1. 普通函数  this 指向 window(函数调用者)
  function fn() {
  console.log('人生的巅峰');
  }
  // fn(); fn.call()
  // 2. 对象的方法 this 指向 对象 o(函数调用者)
  var o = {
   sayHi: function() {
   console.log('人生的巅峰');
  }
  }
  o.sayHi();
  // 3. 构造函数 this 指向 new Star 的实例对象,原型对象里面的this 指向也是 实例对象
  function Star() {};
  new Star();
  // 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
  // btn.onclick = function() {}; // 点击了按钮就可以调用这个函数
  // 5. 定时器函数 this 指向 window
  // setInterval(function() {}, 1000); 这个函数是定时器自动1秒钟调用一次
  // 6. 立即执行函数 this 指向 window
  (function() {
   console.log('人生的巅峰');
  })();
  // 立即执行函数是自动调用

三、改变函数内部  this 的指向

 1.call 方法

  call() 方法调用一个对象,简单理解为调用函数的方式,但是他可以改变函数的 this 指向。

  call() 方法主要作用可以实现继承

  语法:fun.call( 指向对象,参数1,参数2,...)

 2.apply 方法

  apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的this指向。

  语法:fun.apply(thisArg,[argsArray])

  • thisArg:在 fun 函数运行时指定的 this 值
  • argsArray:传递的值,必须包含在数组里面
  • 返回值就是函数的返回值,因为他就是调用函数

  1. 也是调用函数,第二个可以改成函数内部的this指向

  2.但是它的参数必须是数组(伪数组)

  3.apply 的主要应用:利用 apply 借助数学内置对象求最大值(求数字中的最大值:Math.max();)

  例如:

   var arr = [1,55,33,22,4,7];

   Math.max.apply(null,arr); // 并没右指向对象,所以指向对象是 null,也可以写成Math

 3. bind 方法

  bind() 方法不会调用函数。但是能改变函数内部 this 指向

  语法:fun.bind(thisArg,arg1,arg2,...)

  • thisArg:在 fun 函数运行时指定的 this 值
  • arg1,arg2:传递的其他参数
  • 返回由指定的 this 值和初始化参数改造的 原函数拷贝

 4. call   apply   bind 总结

  相同点:

   都可以改变函数内部的 this 指向

  不同点:

   1. call 和 apply 会调用函数,并且改变函数内部 this 指向

   2. call 和 apply 传递的参数不一样, call 传递参数 aru1,aru2...形式,apply 必须数组形式[arg]

   3. bind 不会调用函数,可以改变函数内部 this 的指向

  主要应用场景:

   1. call 经常做继承。

   2. apply 经常跟数组有关系,比如借助数学对象实现数组最大值最小值。

   3. bind 不调用函数,但是还想改变 this 指向。比如改变定时器内部的 this 指向。

四、 严格模式

 JavaScript 除了提供正常模式外,还提供了严格模式(strict  mode) 。ES5 的严格模式是采用具有限制性 JavaScript 变体的一种方式,即在严格的条件下运行 JS 代码。

 严格模式分为:脚本严格模式 和 函数严格模式。

 严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。

 严格模式对正常的 JavaScript 语义做了一些更改:

  1. 消除了 JavaScript· 语法的一些不合理、不严谨之处,减少了一些怪异行为。

  2. 消除代码运行的一些不安全之处,保证代码运行的安全。

  3. 提高编译器效率,增加运行速度。

  4. 禁用了在 ECMAScirpt 的未来版本中可能会定义的一些语法,为未来新版本的 JavaScript 做好铺垫。比如一些保留字如:class,enum,export,extends,import,super 不能做变量名。

五、 严格模式中的变化

 严格模式对 JavaScript 的语法和行为,都做了一些改变。

 1、变量规定

  1. 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,变量都必须先用 var 命令声明,然后再使用。

  2. 严禁删除已经声明变量。例如 delete x; 语法是错误的。

 2、严格模式下 this 的指向问题

  1. 以前在全局作用于函数中的 this 指向 window 对象;严格模式下全局作用于中的 this 是 undefined。

  2. 以前构造函数不加 new 也可以调用,当普通函数, this 指向全局对象;严格模式下,如果构造函数不加 new 调用,this 会报错。

  3. new 实例化的构造函数指向创建的对象实例。

  4. 定时器 this 还是指向 window。

  5. 事件,对象还是指向调用者。

 3、函数变化

  1. 函数不能有重名的 参数

  2. 函数必须声明在顶层,新版本的 JavaScript 会引入 ”块级作用域“(ES6中已引入)。为了与新版本接轨,不允许在非函数的代码块内声明函数。

  更多严格模式要求参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode

  

六、 高阶函数

 高阶函数是对其他函数进行操作的函数,它接收函数作为参数 或 将函数作为返回值输出。

  <script>

   // 方式一

   function  fn (callback){

    callback  && callback();

   }

   fn( function(){ alert("hi") } );

   //  方式二

   function fn(){

    return function() { }

   }

   fn();

  </script>

 此时 fn 就是一个高阶函数

 函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用。最典型的就是作为回调函数。

七、闭包

 1、变量作用域

  变量根据作用域的不同分为两种:全局变量 和 局部变量。

  1.函数内部可以使用全局变量。

  2.函数外部不可以使用局部变量。

  3.当函数执行完毕,本作用域内的局部变量会销毁。

 2、什么是闭包

  闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解:一个作用域可以访问另外一个函数内部的局部变量。局部变量所在的这个函数被称为闭包函数。

  闭包的主要作用:延伸了变量的作用范围。

  经典面试题:利用闭包的方式得到当前小 li 的索引号‘

  <ul> <li>1</li> <li>1</li> <li>1</li> <li>1</li> </ul>

  for( var i =0; i<lis.length;i++){

    // 利用 for 循环创建了 4 个立即执行函数

    // 立即执行函数也称为小闭包,因为立即执行函数里面的任何一个函数都可以使用它的 i 变量

    (function(i){

      lis[ i ].onclick = function(){

        console.log(i);

      }

     })( i );

  }

八、递归

1. 什么是递归?

 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。

 简单理解:函数内部自己调用自己,这个函数就是递归函数。(递归函数的作用和循环效果一样) 

 注意:由于递归很容易发生 ”栈溢出“ 错误(stack overflow),所以必须要加退出条件 return。

2.利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n

        function fn(n) {
if (n == 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));
console.log(fn(4));
// 详细思路 假如用户输入的是3
//return 3 * fn(2)
//return 3 * (2 * fn(1))
//return 3 * (2 * 1)
//return 3 * (2)
//return 6

3.利用递归遍历数组

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head> <body>
<script>
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: '冰箱',
goods: [{
id: 111,
gname: '海尔'
}, {
id: 112,
gname: '美的'
}, ]
}, {
id: 12,
gname: '洗衣机'
}]
}, {
id: 2,
name: '服饰'
}];
// 我们想要做输入id号,就可以返回的数据对象
// 1. 利用 forEach 去遍历里面的每一个对象
function getID(json, id) {
var o = {};
json.forEach(function(item) {
// console.log(item); // 2个数组元素
if (item.id == id) {
// console.log(item);
o = item;
// 2. 我们想要得里层的数据 11 12 可以利用递归函数
// 里面应该有goods这个数组并且数组的长度不为 0
} else if (item.goods && item.goods.length > 0) {
o = getID(item.goods, id);
} });
return o;
}
console.log(getID(data, 1));
console.log(getID(data, 2));
console.log(getID(data, 11));
console.log(getID(data, 12));
console.log(getID(data, 111));
</script>
</body> </html>

4.浅拷贝和深拷贝

 1. 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用。

 2. 深拷贝拷贝多层,每一级别的数据都会拷贝。

 3. Object.assign(target,...sources)  es6新增方法可以浅拷贝

  target:拷贝给谁

  sources:要拷贝哪个

5.使用递归的方式进行深拷贝

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head> <body>
<script>
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.
var obj = {
id: 1,
name: "andy",
msg: {
age: 18
},
color: ["pink", "red"]
};
var o = {};
// 封装函数
function deepCopy(o, obj) {
for (var k in obj) {
// 判断我们的属性值属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = obj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
o[k] = [];
deepCopy(o[k], item);
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
o[k] = {};
deepCopy(o[k], item);
} else {
// 4. 属于简单数据类型
o[k] = item;
}
}
}
deepCopy(o, obj);
console.log(o); var arr = [];
console.log(arr instanceof Object);
o.msg.age = 20;
console.log(obj);
</script>
</body>
</html>

函数高阶(函数,改变函数this指向,高阶函数,闭包,递归)的更多相关文章

  1. 函数和常用模块【day04】:高阶函数(七)

    本节内容 1.介绍 2.具体实用 3.eval()函数 一.介绍 高阶函数:变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数. 二.具体实用 其实说白了,高阶函数功能就 ...

  2. Python高阶函数(Map、Reduce、Filter)和lambda函数一起使用 ,三剑客

    Map函数 map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. 举例说明 比如我们有一个函数f(x)=x2,要把这个函数作用 ...

  3. 高阶函数---swift中的泛型介绍(一步步实现Map函数)

    说明 本文内容均出自函数式 Swift一书, 此处整理仅仅是为了自己日后方便查看, 需要深入研究的话, 可以点进去购买, 支持原作者 本书由 王巍–新浪微博大神翻译 OneV's Den 喵神博客 接 ...

  4. C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址

    C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址 讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当 ...

  5. MFC 消息映射表和虚函数实现消息映射到底谁的效率高

    深入浅出MFC对于虚函数实现方式的缺点,它指出:虚函数耗费大量内存,系统最终将被这些额外负担拖垮. 但是现在对于容量巨大的白菜价格的内存来说,这种额外负担是否已经过时了呢~?    书中提到,虚函数表 ...

  6. C++反汇编第二讲,反汇编中识别虚表指针,以及指向的虚函数地址

    讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当然也可以看原博客链接: http://blog.csdn.net ...

  7. 想精度高,可以考虑用c语言中的函数gettimeofday

    大家好: 在 win32 + bcb 时, 有个 GetTickCount() 返回第统启动到现在的 tick, 单位 ms.请问在 Linux + qt5 怎样实现呢? 如果用 QDateTime ...

  8. js中this指向、箭头函数

    普通函数:this指向分为4种情况,1. obj.getName();//指向obj2.getName();//非严格模式下,指向window,严格模式下为undefined3. var a = ne ...

  9. ES6 箭头函数下的this指向和普通函数的this对比

    首先在网上摘抄借鉴了一段代码, 然后再这段代码里面进行分析,通过比较ES6的箭头函数和普通函数的this指指向, 分析其中的不同之处.下面就是代码片段var name = "window&q ...

  10. JS---DOM---为同一个元素绑定多个不同事件指向同一个事件处理函数

    为同一个元素绑定多个不同事件指向同一个事件处理函数 1. 用了switch(e.type){} 来修改 2. break <input type="button" value ...

随机推荐

  1. gcc 交叉工具链中工具使用(arm-linux-xxx)

    在Ubuntu系统中使用 gcc 系列工具是在PC机上使用 arm-linux-gcc 编译的目标 是在 arm CPU上使用 一.安装交叉编译工具链 1. 编译工具怎么获取 1)从官网 http:/ ...

  2. Harbor私有镜像仓库(下)

    Harbor私有镜像仓库(下) 链接:https://pan.baidu.com/s/1MAb0dllUwmoOk7TeVCZOVQ 提取码:ldt5 复制这段内容后打开百度网盘手机App,操作更方便 ...

  3. jenkins连接gitlab,提示returned status code 128,附解决办法

    在项目中配置git仓库地址,报无权限 Failed to connect to repository : Command "D:\Program Files\Git\mingw64\bin\ ...

  4. proxy汇总-1

    1.apt-get的proxy 新建/etc/apt/apt.conf.d目录下新建10proxy文件,添加: Acquire::http::proxy"http://xx.xx.xx.xx ...

  5. 【leetcode】987. Vertical Order Traversal of a Binary Tree

    题目如下: Given a binary tree, return the vertical order traversal of its nodes values. For each node at ...

  6. hdu 1540 Tunnel Warfare (线段树,维护当前最大连续区间)

    Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively i ...

  7. 【Flutter学习】基本组件之BottomNavigationBar底部导航栏

    一,概述 BottomNavigationBar即是底部导航栏控件,显示在页面底部的设计控件,用于在试图切换,底部导航栏包含多个标签.图标或者两者搭配的形式,简而言之提供了顶级视图之间的快速导航. 二 ...

  8. linux基础知识-常用命令

    ifconfig :查看当前ip hostname:查看主机名 vim /etc/hosts:修改地址映射 service iptables status : 查看防火墙状态 chkconfig ip ...

  9. tcp和udp得区别

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议 UDP 是User Datagram Protocol,即 用户 ...

  10. Python进阶:set和dict/对象引用、可变性和垃圾回收/元类编程/迭代器和生成器

    frozenset:不可变集合,无序,不重复 dict上的特性: 1. dict的key或者set的值 都必须是可以hash的(不可变对象 都是可hash的, str, fronzenset, tup ...