2022-01-18 深入JavaScript高级语法(二)

1、理解JavaScript纯函数

1.1、概念

  • 确定的输入,一定会产生确定的输出
  • 函数在执行过程中,不能产生副作用

副作用的理解:
在执行一个函数时,除了返回函数值之外,还对调用函数产生了附加影响,比如修改了全局变量,修改参数或者改变外部的存储。

1.2、纯函数的举例

function foo(num1, num2) {
  return num1 * 2 + num2 *3;
}
function test(info) {
  return {
    ...info,
    age: 100
  };
}
  • 三:数组的slice方法

2、JavaScript柯里化

2.1、概念

只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数,这个过程就称之为柯里化

function foo(m, n, x, y) {
  return m + n + x + y;
}

foo(10, 20, 30, 40);

// 柯里化过程:把foo转换为bar的过程就叫做柯里化
function bar(m) {
  return function(n) {
    return function(x) {
      return function(y) {
        return m + n + x + y;
      }
    }
  }
}
bar(10)(20)(30)(40);

// 简化柯里化的代码
m => n => x => y => m + n + x + y;

2.2、 为什么需要有柯里化

2.2.1、单一职责的原则

  • 在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理
  • 那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果
function sum(x) {
  x = x + 2;
  return function(y) {
    y = y* 2;
    return function(z) {
      z = z * z;
      
      return x + y + z;
    }
  }
}

2.2.2、逻辑的复用

  • 举例
function sum(m) {
  m = m * m; // 复用的逻辑
  return function(n) {
    return m + n;
  }
}

var addNum = sum(5);
addNum(10);
addNum(20);

2.3、柯里化函数的实现

function hyCurrying(fn) {
  return function curried(...args) {
    // 判断当前已经接收的参数的个数(args.length),和函数(fn)本身需要接收的参数个数(fn.length)是否一致了
    if (args.length >= fn.length) {
      // fn(...args);
      // 保证调curried函数的this跟调fn函数的this是一样的
      // fn.call(this, ...args);
      return fn.apply(this, args);
    } else {
      // 没有达到个数时,需要返回一个新的函数,继续来接收新的参数
      return function curried2(...args2) {
        // 接收到参数后,需要递归调用curried来检查函数的个数是否达到
        return curried.apply(this, [...args, ...args2]);
      }
    }
  }
}

function add(x, y, z) {
  return x + y + z;
}

var curryAdd = hyCurrying(add);
curryAdd(10, 20, 30);
curryAdd(10, 20)(30);
curryAdd(10)(20)(30);

3、组合函数

3.1、概念

组合(Compose)函数是在js开发过程中一种对函数的使用技巧、模式

  • 比如我们现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn1,这两个函数是依次执行
  • 那么如果每次我们都需要进行两个函数的调用操作上就会显得重复
  • 那么是否可以将这两个函数组合起来,自动依次调用呢?
  • 这个过程就是对函数的组合,我们称之为组合函数(Compose Function)

3.2、举例

  • 简单举例
function double(num) {
  return num * 2;
}

function square(num) {
  return num * num;
}

var count = 10;
var result = square(double(count));
console.log(result);

function composeFn(m, n) {
  return function(count) {
    return n(m(count));
  }
}

var newFn = composeFn(double, square);
console.log(newFn(10));
  • 通用实现
function hyCompose(...fns) {
  var length = fns.length;
  for (var i = 0; i < length; i++) {
    if (typeof fns[i] !== 'function') {
      throw new Typeerror("Expected arguments are functions")
    }
  }
  
  return function compose(...args) {
    var index = 0;
    var result = length ? fns[index].apply(this, args) : args;
    while(++index < length) {
      result = fns[index].call(this, result);
    }
    return result;
  }
}

function double(m) {
  return m * 2;
}

function square(n) {
  return n * 2;
}

var newFn = hyCompose(double, square);
console.log(newFn(10, 2));

4、with语句 —— 可以形成自己的作用域

注:了解就可以,现在已经不推荐使用了。在严格模式下使用会报错。

var message = "Hello World";

// with语句:可以形成自己的作用域
var obj = {name: "why", age: 18, message: "obj message"};

function foo() {
  function bar() {
    with(obj) {
      // 查找作用域链:obj -> bar -> foo -> 全局
      console.log(message);
    }
  }
  bar();
}

foo();

5、eval函数

注:了解就可以。
eval是一个特殊的函数,它可以将传入的字符串当做hs代码来执行。

var jsString = 'var message = "Hello World";console.log(message);';

eval(jsString);

不建议在开发中使用eval:

  • eval代码的可读性非常差(代码的可读性时高质量代码的重要原则)
  • eval是一个字符串,那么有可能在执行的过程中被刻意篡改,那么可能会造成被攻击的风险
  • eval的执行必须经过js解释器,不能被js引擎优化

6、严格模式

6.1、概念

在ES5标准中,js提出了严格模式的概念(Strict Mode):

  • 严格模式很好理解,是一种具有限制性的js模式,从而使代码隐式的脱离了“懒散(sloppy)模式”
  • 支持严格模式的浏览器在检测到代码中有严格模式时,会以更加严格的方式对代码进行检测和执行

"use strict";

6.2、严格模式下常见的限制

6.2.1、禁止意外创建全局变量

"use strict";
message = 'hello world';
console.log(message);

function foo() {
    age = 20;
}

foo();
console.log(age);

6.2.2、不允许函数有相同的参数名称

"use strict";
function foo(x, y, x) {
  // 30 20 30 后面的x把前面的x覆盖了
  console.log(x, y, x); 
}

foo(10, 20, 30);

6.2.3、静默错误

"use strict";
true.name = 'abc';
NaN = 123;

var obj = {};
Object.defineProperty(obj, 'name', {
  // 不可配置(严格模式下该属性不能通过delete删除)
  configurable: false,
  // 只读(严格模式下不能进行赋值操作)
  writable: false,
  value: 'why'
});

console.log(obj.name)
obj.name = 'kobe';
delete obj.name;

6.2.4、不允许使用原先的八进制格式

"use strict";
// 原来的八进制写法:以数字0开头
var num = 0123;
console.log(num);

补充:es6后的写法

var num = 0o123; // 八进制
var num2 = 0x123; // 十六进制
var num3 = 0b100; // 二进制

6.2.5、with语句不允许使用

6.2.6、eval韩式不会向上引用变量

"use strict";
var jsString = 'var message = "hello world"; console.log(message);'
eval(jsString);

console.log(message); // 报错:message is not defined

*6.2.7、严格模式下的this

在严格模式下,自执行函数(默认绑定)会指向undefined

"use strict";
function foo() {
    console.log(this); // undefined
}
foo();

强调:setTimeout在严格/非严格的模式下,传入的回调函数(非箭头函数的情况下)的this总是指向window的。伪代码:

setTimeout(fn, delay);
// fn的调用方式
fn.apply(this); // this总是指向window
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值