Java函数式编程-手写柯里化函数-组合函数-严格模式
1、柯里化函数的实现(自己实现)(面试题)
// 柯里化函数的实现hhCurrying
function hhCurrying(fn) {
function curried(...args) {
/*判断当前已经接收的参数的个数, 和参数本身需要接受的参数
是否已经一致了*/
// 1.当已经传入的参数 大于等于 需要的参数时, 就执行函数
//args.length:当前已经接收的参数个数,
//fn.length函数本身需要接收的参数的个数
if (args.length >= fn.length) {
// fn.call(this, ...args)
return fn.apply(this, args)
} else {
// 没有达到个数时, 需要返回一个新的函数, 继续来接收的参数
function curried2(...args2) {
/* 接收到参数后, 需要递归调用curried来检查函数的参数
是否达到一致*/
//concat函数:连接两个数组
return curried.apply(this, args.concat(args2))
}
return curried2
}
}
return curried
}
//测试1
function add1(x, y, z) {
return x + y + z
}
//转为柯里化函数
var curryAdd = hhCurrying(add1)
console.log(curryAdd(10, 20, 30)) //60
console.log(curryAdd(10, 20)(30)) //60
console.log(curryAdd(10)(20)(30)) //60
//测试2
function foo(x, y, z) {
return x + y + z;
}
var result1 = foo.call({}, 1, 2, 3);
console.log(result1); //6
var curryFoo = hhCurrying(foo);
var result2 = curryFoo.call({}, 1)(2)(4);
console.log(result2); //7
2、组合函数的理解
- (1)现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的,那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复。
- 解决方案:将这两个函数组合起来,自动依次调用,
- 这个过程就是对函数的组合,我们称之为 组合函数(Compose Function)
//未组合:
function double(num) {
return num * 2;
}
function square(num) {
return num ** 2;
}
var count = 10;
var result = square(double(count));
console.log(result); //400
// 实现最简单的组合函数
function composeFn(m, n) {
return function (count) {
return n(m(count));
};
}
var newFn = composeFn(double, square);
console.log(newFn(10)); //400
3、 通用组合函数的实现(自己实现)
function hhCompose(...fns) {
var length = fns.length
//传入的参数必须是一个函数,否则抛出错误
for (var i = 0; i < length; i++) {
if (typeof fns[i] !== 'function') {
throw new TypeError("Expected arguments are functions")
}
}
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
}
return compose
}
//测试
function double(m) {
return m * 2;
}
function square(n) {
return n ** 2;
}
var newFn = hhCompose(double, square);
console.log(newFn(10)); //400
4、JS额外知识补充-with语句-eval函数-严格模式
4.1、with语句(已经不建议使用)(严格模式下不允许包含with语句)
作用:with语句 扩展一个语句的作用域链(可以形成自己的作用域链)
var message = "Hello World";
var obj = { name: "why", age: 18, message: "obj message" };
// with语句: 可以形成自己的作用域
function foo() {
function bar() {
with (obj) {
console.log(message); //obj message
console.log("------");
}
}
bar();
}
foo();
var info = { name: "kobe" };
with (info) {
console.log(name); //kobe
}
4.2、eval函数(全局函数)
- (1)作用:eval是一个特殊的函数,它可以将传入的字符串当做JavaScript代码来运行。
- (2)不建议在开发中使用eval:
①eval代码的可读性非常的差(代码的可读性是高质量代码的重要原则)
②eval是一个字符串,那么有可能在执行的过程中被刻意篡改,那么可能会造成被攻击的风险;
③eval的执行必须经过JS解释器,不能被JS引擎优化;
var jsString = 'var message = "Hello World"; console.log(message);';
eval(jsString); //Hello World
4.3、 严格模式(‘‘use strict’’;)
- 严格模式限制
- (1)无法意外的创建全局变量
- (2)使引起静默失败(silently fail,注:不报错也没有任何效果)的赋值操作抛出异常
- (3)严格模式下试图删除不可删除的属性
- (4)不允许函数参数有相同的名称
- (5)不允许0的八进制语法
- (6)不允许使用with
- (7)eval不再为上层引用变量
- (8)this绑定不会默认转成对象
"use strict";
// 1. 禁止意外创建全局变量
message = "Hello World"
//会报message is not defined的错误,message未声明
console.log(message)
function foo() {
age = 20 //会报age is not defined的错误,age未声明
}
foo()
console.log(age)
"use strict";
// 2.不允许函数有相同的参数名称
function foo(x, y, x) {
console.log(x, y, x)
//会报Duplicate parameter name not allowed in this context的错误,
//在此上下文中不允许重复的参数名称
}
foo(10, 20, 30)
// 3.静默错误/试图删除不可删除的属性
"use strict";
true.name = "abc";
//Cannot create property 'name' on boolean 'true'
NaN = 123;
// Cannot assign to read only property 'NaN' of object '#<Object>'
var obj = {};
Object.defineProperty(obj, "name", {
configurable: false,
writable: false,
value: "fifih",
});
console.log(obj.name); //fifih
// obj.name = "kobe";
//Cannot assign to read only property 'name' of object '#<Object>'
delete obj.name;
// Cannot delete property 'name' of #<Object>
"use strict";
// 4.不允许使用原先的八进制格式 0123 改成0O123就可以
var num = 0o123 // 八进制
var num2 = 0x123 // 十六进制
var num3 = 0b100 // 二进制
console.log(num, num2, num3) //83 294 4
"use strict";
// 5.with语句不允许使用
// 6.eval函数不会向上引用变量了
message = "Hello eval"
var jsString =
'"use strict"; var message = "Hello World"; console.log(message);'
eval(jsString) //Hello World
console.log(message) //报错 message is not defined