zoukankan      html  css  js  c++  java
  • 带你学习javascript的函数进阶(二)

    1 严格模式

    1.1 什么是严格模式

    JavaScript除了提供正常模式外,还提供了严格模式(strict mode)。ES5的严格模式是采用具有限制性Javascript变体的一种方式。即在严格的条件下运行js代码。
    严格模式在IE10以上版本的浏览器中才会被支持,旧版本浏览器会被忽略。
    严格模式对正常的javascript语义做了一些更改:

    1. 消除了Javascrip语法的一些不合理、不严谨之处,减少了一些怪异行为。
    2. 消除了代码运行的一些不安全之处,保证代码运行的安全。
    3. 提高编译器效率,增加运行速度。
    4. 禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的Javascript做好铺垫。比

    如一些保留字:class,enum,export,extends,import,super不能做变量。

    1.2 开启严格模式

    严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为脚本开启严格模式和
    为函数开启严格模式两种情况

    1. 为脚本整个脚本开启严格模式

    为整个脚步文件开启严格模式,需要在所有语句之前做一个特定语句"use strict"

    <scirpt>
      "use strict"
    	console.log("这是最严格模式")
     </scirpt>
    
    1. 为函数开启严格模式

    要给某个函数开启严格模式,需要把"use strict";(或'use strict')声明放在函数体所有语句前。

    <script>
     	function fn() {
    		'use strict' //下面的代码按照严格模式进行
    	} 
     </script>
    

    3.3 严格模式中的变化

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

    1. 变量规定
    • 在正常模式中,如果一个变量没有声明就赋值,默认的事全局变量。
    • var 命令声明,然后再使用
    <script>
      ‘use strict’
    	num = 10
    	console.log(num)
     </script>
    

    效果如下图
    image.png
    严禁删除已经声明的变量。

    1. 严格模式下this指向问题
    • 以前在全局作用域函数中的this指向window对象。
    • 严格模式下全局作用域中函数中的this事undefined。
    • 以前构造函数时不加new也可以调用,当普通函数,this指向全局对象。
    • 严格模式下,如果构造函数不加new调用,this会报错。 new实例化的构造函数指向创建的对象实例。
    • 严格模式下,定时器里的this指向还是window.
    • 严格模式下,事件、对象还是指向调用者。
    1. 函数变化
    • 严格模式下函数不能有重名的参数
    • 函数必须声明在顶层,新版本的js会引入“块级作用域”(ES6中已引入)。为了与新版本接轨,不允许在非函数的代码块内声明函数,如在if,for语句中声明函数。

    2 高阶函数

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

    function fn(callback) {
    	callback && callback()
    }
    fn(function(){
    	alert('lanfeng')
    })
    
    function fn() {
    	return function() {
      }
    }
    fn()
    

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

    3 闭包

    3.1 变量作用域

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

    1. 函数内部可以使用全局变量
    2. 函数外部不可以使用局部变量
    3. 当函数执行完时,本作用域内的局部变量会被销毁。

    3.2 什么是闭包

    闭包指有权访问另外一个函数作用域中变量的函数。也就是说,一个作用域可以访问另外一个函数内部的局部变量。

    //fn 外面的作用域可以访问fn内部的局部变量
    function fn() {
    	var num = 10
      function fun () {
      	console.log(num) //可以访问num
      }
      return fun
    }
    var f = fn()
    f() //10
    
    //fn 外面的作用域可以访问fn内部的局部变量
    function fn() {
    	var num = 10
      
      // 返回一个匿名函数
      return function() { 
      	console.log(num) //可以访问num
      }
    }
    var f = fn()
    f() //10
    

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

    3.3 闭包案例

    1. 循环注册点击事件
    //html
    <ul class="nav">
      <li>a</li>
      <li>b</li>
      <li>c</li>
      <li>d</li>
    </ul>
    //js
    //点击li输出当前li的索引
    //利用动态田径属性方式
    var lis = document.querySelector('.nav').querySelectorAll('li')
    for(var i=0 ;i<lis.length; i++) {
      lis.index = i
    	lis[i].onclick = function() {
      	console.log(this.index)
      }
    }
    //利用闭包的方式
    var lis = document.querySelector('.nav').querySelectorAll('li')
    for(var i=0 ;i<lis.length; i++) {
      (function(i) {
      	lis[i].onclick = function() {
      	console.log(i)
      }
      })(i)
    	
    }
    
    1. 循环中的setTimeout()
    //html
    <ul class="nav">
      <li>a</li>
      <li>b</li>
      <li>c</li>
      <li>d</li>
    </ul>
    //js
    //利用闭包
    var lis = document.querySelector('.nav').querySelectorAll('li')
    for(var i=0 ;i<lis.length; i++) {
      (function(i){
      	setTimeout(function() {
        	console.log(lis[i].innerHTML)
        },3000)
      })(i)
    }
    
    1. 计算打车价格
    var car = (function() {
    		var start = 13;
        var total = 0;
      return {
        //正常价格
      		price: function(n) {
          	if(n <= 3) {
            	total = start
            } else {
            	total = start + (n-3)* 5
            	}
            return total;
          }, 
        	// 拥堵之后
        	yd: function(flag) {
          	flag? total+ 10 :total
          } 
      	}
    	})()
    console.log(car.price(5))
    console.log(car.yd(true))
    

    3.4 闭包总结

    1. 闭包是什么?

    闭包就是一个函数(一个作用域可以访问另外一个函数的局部变量)

    1. 闭包的作用是什么?

    延伸变量的作用范围

    4 递归

    4.1 什么是递归

    如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
    递归函数的作用和循环效果一样
    由于递归很容易发生“栈溢出”(stack overflow),所以必须要加退出条件 return

    4.2 利用递归求数学题

    1. 求123...*n
    function fn(n) {
      if(n = 1) {
      	return 1
      }
    	return n * fn(n-1)
    }
    console.log(fn(3)) // 6
    

    4.3 利用递归求:根据id返回对应的数据对象

    var data = [{
    	id:1,
      name:'家电',
      goods: [
        {
          id: 11,
          gname: '冰箱'
        },
        {
        	id: 12,
          gname: '洗衣机'
        }
      ]
    },
                {
                id: 2,
                  name: '服饰'
                }
     ]
    function getObj(arr, id) {
      var o = {}
    	arr.forEach(function(item){
      	if(item.id === id) {
        	o= item
        } else if(item.goods && item.goods.length>0) {
        		o =getObj(item.goods, id);
        }
      })
      return o
    }
    console.log(getObj(data, 1))
    

    5 递归

    5.1 浅拷贝和深拷贝

    1. 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用。
    2. 深拷贝拷贝多层,每一级别的数据都会拷贝。
    3. Object.assign(target, ...sources) es6新增方法可以浅拷贝
    var obj = {
    	id: 1,
      name: 'andy',
      msg: {
       age: 18
      }
    }
    var o = {}
    for(var k in obj) {
      // k是属性名
    	o[k] = obj[k]
    }
    console.log(o)
    o.msg.age = 20
    console.log(obj) //obj发生变化
    
    //用es6语法糖
    Object.assign(o, obj)
    
    

    image.png

    //深拷贝,应用递归的方法
    function deepCopy(newObj, oldObj) {
    	for(var k in oldObj) {
      	//判断我们的属性值属于哪种类型
        var item = oldObj[k]
        // 判断是否是数组
        if(item instanceof Array) {
        	newObj[k] = []
          deepCopy(newObj[k], item)
          
        } else if(item instanceof Object) {
          //判断是否是对象
          newObj[k] = {}
          deepCopy(newObj[k], item)
        } else { // 属于简单数据类型
        	 newObj[k] = item
        }  
        
      }
    }
    deepCopy(o,obj)
    console.log(o)
    
    

    总结

    本篇文章主要分享了函数的严格模式、高阶函数、闭包、递归、深拷贝、浅拷贝等知识点的用法及应用。如果想了解更多,请扫描二维码
    qrcode_for_gh_4d3763fa9780_258 (1).jpg

  • 相关阅读:
    C语言点滴
    随便记点什么
    STL的使用
    Linux下OTG支持USB摄像头
    socket编程实战-调试
    socket编程实战-bind端口占用问题
    socket编程实战-tcp_tw_recycle问题
    socket编程实战-connect超时问题
    BT[3]-BLE广播详解
    BT[2]-BLE初体验:心率计
  • 原文地址:https://www.cnblogs.com/lfcss/p/12400411.html
Copyright © 2011-2022 走看看