01 | 函数式vs.面向对象:响应未知和不确定
01 | 函数式vs.面向对象:响应未知和不确定
讲述:石川
时长16:42大小15.25M
函数式编程
函数是什么、如何使用?
函数中都有哪些副作用?
减少副作用:纯函数和不可变
面向对象编程
对象是什么、如何创建?
为什么需要封装、重用和继承?
什么是基于原型的继承?
总结
思考题
延伸阅读
赞 10
提建议
精选留言(23)
- Hello,Tomrrow2022-09-21 来自北京JS 中的const 是否是可变,要分情况。 如果 const 声明的变量赋值给了原始类型,如数字、bool、字符串,此时就是不可变的; 如果 const 声明的变量赋值了复合类型,如数组、对象,此时变量指向的地址不可比变,但是复合类型的内容还是可以调整的, 如更改对象的属性值
作者回复: 正解
19 - null2022-09-19 来自北京单独这一篇就值回票价了,学到了很多东西😁
作者回复: 很高兴你这么说,看来以后每篇都是赚的了😄
7 - I keep my ideals...2022-09-20 来自北京我认为const对于值类型来说是不可变的,但是对应引用类型来说就不一定了(可以保证引用类型的存储地址不变,但是不能保证里面存储的内容不变)
作者回复: 差不多是这个意思,或者也可以说对于“原始类型值”,如数字、字符串是不可变的。对于像数组这样的“对象类型值”,仍然是可变的。所以常量只是做到“赋值动作”的不可变,而不是做到“值”本身的不可变
4 - Geek_dc85eb2022-09-20 来自北京开发中const一般是不变的
作者回复: 这里的不可变我们要搞清楚是值不可变,还是变量的不可变。 比如我们给num赋值数组,值还是可变。 const num = [3]; num[0] = 5; // 返回:5 反之,我们没法拷贝原数组,slice后再赋值给原来的变量 const sliceNums = [1,2,3,4,5]; sliceNums = sliceNums.slice(0,2); // 返回错误 所以const还是蛮多坑的,在Java中用的就是final,而不是const。 也是因为这些坑,在JS中,通常const更多用于原始类型的值,比如数理常量、字节顺序或版本号: const H0 = 74; // 哈勃常数 (km/s/Mpc) const PI = 3.141592; // 圆周率 const C = 299792.458; // 光速 (km/s)
4 - weineel2022-10-09 来自北京副作用的概念有点刷新认知。 老师说的副作用,指函数不可控的外部环境。 我之前认为的副作用,是函数会对外部环境产生影响,比如改变全局变量的值。 还有一个疑问,如果函数只改变了全局变量的值,并没有使用它进行计算(相同的输入,会有相同的输出),这个函数还是纯函数吗? 按我之前的对副作用的理解,就会认为不是纯函数了。展开
作者回复: 函数会对外部环境产生影响,比如改变全局变量的值也是副作用。 如果函数只改变了全局变量的值,这里主要造成的问题是不可变。 关于一个函数是不是纯函数主要是看同样的输入,输出是否相同。
共 3 条评论2 - 依韵2022-10-13 来自北京> “纯函数”对值只影响一次,而“不可变”完全不影响。 针对这个还是有点疑问。 即然是从返回值的角度来看,那么能保持幂等的纯函数,返回一个新值,这个新值是基于输入创造的,可以当成是影响,就当是影响了一次。 那对不可变来说,如 `slice` 也返回了一个新值,这个新值是基于输入(原始数组)创造的,为什么要当成是完全不影响呢。 这点如何理解,还希望得到解答。 写完这个问题, 我意识到是不是说纯函数和不可变描述的是不同的角度,纯函数是从返回值的角度来看,不可变是从输入的角度来看,这样理解是否正确? 如果获取数组中某个子数组的函数,如果使用 `Array.prototype.slice` 来实现,那么是纯函数,也是不可变。换成 `Array.prototype.splice` 来实现就仅仅是纯函数,而不是不可变。 如 `conat add = (a,b) => a + b;` add 是纯函数,也是不可变。展开
作者回复: 我们还是可以用slice和splice来举例子 这里每次输入0,3,slice只影响结果一次。而splice每次都影响。 var arr = [1, 2, 3, 4, 5]; /***纯函数***/ arr.slice(0, 3); // 返回 [1, 2, 3] arr.slice(0, 3); // 返回 [1, 2, 3] arr.slice(0, 3); // 返回 [1, 2, 3] /***非纯函数***/ arr.splice(0, 3); // 返回 [1, 2, 3] arr.splice(0, 3); // 返回 [4, 5] arr.splice(0, 3); // 返回 [] slice不可变是说它对原数组没影响,而splice会影响,所以是可变。 var arrA = [1, 2, 3, 4, 5]; /***不可变***/ var arrB = arrA.slice(0, 3); console.log(arrA); // 返回 [1, 2, 3, 4, 5] /***可变***/ var arrC = arrA.splice(0, 3); console.log(arrA); // 返回 [1, 2, 3]
2 - 朱基2022-10-13 来自北京本讲属于Javascript编程语言的内功与心法,感谢石川老师以个人的修悟为我们道来,有幸。
作者回复: 幸会,也感谢一路有你。
1 - Kobe的篮球2022-09-22 来自北京编程模式很多地方也叫编程范式吧,JS是基于原型的,原型编程这种编程范式能讲下吗
作者回复: 是的,有些地方叫编程范式,都是programming paradigm。基于原型的继承,delegation,组合后面都会深入讲
1 - 樱花葬2022-09-20 来自北京第一次接触纯函数的概念是在react中接触到的,今天看到这篇文章比较清晰的明白了究竟什么是纯函数,同时引发了一个疑问---react的纯函数与js这里提到的纯函数是同一个概念吗?如果不是的话他们之间有什么区别吗?
作者回复: 如果一个函数只要输入值一样,返回的结果就一样,那这个函数就是纯函数。同理,如果React组件通过相同的state和props得出相同的输出,则称它是纯组件。所以我认为基本原则是一致的。正好提到React,下一节,我们也会从不可变的角度来看看React中的state和props。
共 2 条评论1 - 南城2022-09-20 来自北京试读白嫖!能免费看四章(催更帖)
作者回复: 对,先看看再说,觉得好再买
1 - 安安安2023-01-29 来自北京幂等的意思应该是 f(x) === f(f(x)) 吧,文中为啥是Math.round(((0.5)))?
- WGH丶2022-12-18 来自海南妙啊~值得一读、二读。三读。很多例子恰到好处,作者牛逼!
作者回复: 谢谢支持~
- 海是蓝天的倒影2022-12-13 来自海南这是我见过函数式和面向对象讲得最透彻的,没有之一。 感谢老师
作者回复: 谢谢支持~
- MarkTang2022-12-11 来自海南const 是否可变要看类型是否是基础类型,如果是基础类型则是不可变的,如果是引用类型则是可变的
作者回复: 是的
- 235682022-11-07 来自北京对于一个基础不扎实原理不清晰的小白来说 能学习到老师的课真的是太好了!
作者回复: 谢谢支持~
- 雨中送陈萍萍2022-11-03 来自北京老师讲的确实不错!! 先回答问题, 对于const来说,我认为只在某种意义上说是不可变的,const创建一个值的引用(指向的内存地址),后续无法通过赋值的方式改变这个引用。如果const声明初始赋值是原始类型,后续无法改变初始值,但是如果初始赋值类型是引用类型(对象类型),后续可以改变初始对象,也就不符合不可变的原则。 其次,老师把FP比作工具,把OOP比作对象,然后工具是服务于对象,一下子就把两者链接上,两者从我脑海中孤立存在变成了统一有机的整体,加深了对两者的理解。另外,原型链的讲解和传统继承,基于原型链的继承的区别的讲解,都简单易懂,真真不错!展开
作者回复: 正解!谢谢支持~
- joel2022-10-20 来自广东1、副作用:不可控的外部环境
- Mick2022-10-09 来自上海不止课程能学到很多东西,留言区也有很多干货啊
- ll2022-09-26 来自北京之前好像在哪里看到过,函数式编程两个核心,1.值不可变,2.函数可以作为值。然后才有后来的高阶函数之类的应用等等;java 这种oop在继承,和创建对象时是“硬”拷贝的,先找到,在复制,可能会比较占内存;而js是“软”拷贝, 复制的是函数方法的“地址”或者地址变量?, 地址变量储存地址,其中储存的地址值是不可变的,但变量储存的地址可变。感觉Object.create()像是创建个地址变量,初始存Widget.prototype 这个地址,不知道这样理解对不对展开
作者回复: 这里有3个不同的概念: 1. 对象的引用,这里a,b两个不同的变量,引用的对象值地址是相同的 var a = { name : "a" }; var b = a; console.log(b.name); // 返回"a" a.name = "b"; console.log(b.name); // 返回"b" 2. 对象的拷贝,浅拷贝只拷贝第一层的内容,深拷贝会拷贝嵌套的对象内容 3. 对象的创建,这里用Notice.prototype = Object.create(Widget.prototype)这样的方式,对应的是class中extend的功能,所以基于Notice创建的对象notice1会既继承Widget的原型,也继承Notice的原型
- Charlescliff2022-09-23 来自北京强烈推荐You don't know JS系列
作者回复: 是很不错的,除了OLOO vs OOP 可以辩证的看外,不过即使是这一点,也体现了Kyle鲜明的个性