一、函数的定义方式

 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. 创建Uboot 环境变量 bin 文件

    As we know, the bootloader stores its configuration into an area of the flash called the environment ...

  2. Oracle varchar2或char类型的byte和char的区别

    那其中的BYTE和CHAR有什么区别呢 BYTE,用字节指定:VARCHAR2(10 BYTE).这能支持最多10字节的数据,在一个多字节字符集中,这可能只是两个字符.采用多字节字符集时,字节与字符并 ...

  3. 二、sqlyog的使用

    1. 创建数据库. 注意字符集 2.创建表 注意 表名.引擎名.字符集

  4. error: device unauthorized.

    1 执行 adb install   com.taobao.taobao_250.apk 报错 2 先看手机是不是未授权,执行命令之后,手机回弹出授权信息,点击确认就行了

  5. bootStrap @media 用法

    一. @media 格式 @media all and (min-width:xxx) and (max-width:xxx) (亦可以写成@media all and (min-width:xxx) ...

  6. C语言小笔记(1)

    枚举类型的大小是4,和一个int整形大小一样 就是最后一个逗号后面的表达式的值,比如: int a=1,b; b=(a+1,a+2,a+3); 那么b的值就是a+3,也就是4 函数名   :print ...

  7. 阿里巴巴下一代云分析型数据库AnalyticDB入选Forrester Wave™ 云数仓评估报告 解读

    前言近期, 全球权威IT咨询机构Forrester发布"The Forrester WaveTM: CloudData Warehouse Q4 2018"研究报告,阿里巴巴分析型 ...

  8. python的OS模块生成100个txt文件

    #!/user/bin/env/python35 # -*-coding:utf-8-*- # author:Keekuun """ 问题:生成一个文件夹,文件夹下面生成 ...

  9. php开发面试题---PHP为什么不安全,主要有那些安全问题(整理)

    php开发面试题---PHP为什么不安全及常见的攻击方式(整理) 一.总结 一句话总结: 其实安全和语言关系不大,主要和程序员关系比较大,php也就是因为是弱类型语言,所以不如java健壮,php会遇 ...

  10. svn 版本管理,trunk(主干),branch(分支),merge(合并)

    svn 版本管理,主要对trunk(主干).branch(分支).merge(合并)进行说明. svn作为一个常用的版本管理工具,一些基本操作必须要会,在这里整理一下自己使用svn的一些体会: svn ...