22 | new Function('x = 100')();:函数的类化是对动态与静态系统的再次统一
22 | new Function('x = 100')();:函数的类化是对动态与静态系统的再次统一
讲述:周爱民
时长14:58大小12.00M
函数的动态创建
几种动态函数的构造器
函数的三个组件
动态函数的创建过程
作为一个函数
唯一一点不同
结尾
赞 2
提建议
精选留言(10)
- 独钓寒江雪2020-01-03今天读完了专栏必学内容的最后一讲,跟着老师的步伐一路走来,很艰辛,同时也收获很多,通过一行极简的代码去洞悉一门语言的核心原理,也是我一直梦想着能做到的事,向老师致敬! 其实,可以说,看这种底层的东西,每一讲都很吃力,要想有更深入的理解,必须再花时间回过头反复研读;其实,阅读专栏,很多时候也是一种思维的提升,比如以前只知道变量提升,却没想过为什么要提升;知道...运算符,却说不出为什么可以用它来展开对象。。。 或许专栏短期内对开发能力不会有多么显著的提升,但我相信,因为对语言本质的洞悉而产生的自信以及思想层面的提升,将会使我在前端走的更远。衷心的感谢🙏展开
作者回复: 🙏
7 - 行问2020-01-03new Function(x) vs Function(x) 没什么区别。如果是“类化”的话,也是没什么区别吗?在使用 class 声明一个类时,new class 与 class 直接调用。 函数是对象的概念比较清晰,明了。这让我想起之前的 "null",请教个问题,在通常的开发中,会把一些变量释放空间,把值置为 null, 那么如果是置为 {} 呢?如下: var a = null 和 var a = {},是否有大差异? 我的理解是 {} 会存放在“堆空间”占据内存,但同时它是一个空对象,null 也是一个什么都没有的空对象,但 null 也是其它对象的原型,所以也会有 Object.create(null) 不知道周大能否看懂我的逻辑? 感谢展开
作者回复: Oh. 这个 > new Function(x) vs Function(x) 没什么区别 并不算是很特别的特例。你应该记得new AClass()的时候,允许“用户代码直接返回对象,而不是直接使用this” 这个特性对吧,其实这就是这个特性的应用。因为当用户代码返回自己创建的对象是,用不用new,效果都是一样的了。——所以,这里的意思是说,Function()在实现时也是自己返回了对象,而没有使用缺省new给他创建的this。 理论上,这对类化来说也是适用的。因为类化也允许用户代码返回对象来替代this。但是——呵呵,如果你用“class X...”来声明类,那么这个X是只能用new来调用的,而不能直接当做函数调用。 ``` > X() TypeError: Class constructor X cannot be invoked without 'new' ``` 关于null值和{}。其实null值是一个特殊性,它是真的“什么也没有”,你甚至可以将它理解为C里面的#0。而它是对象(typeof null),以及它能作为其它对象或类的原型,只是一个语言设计,而与它的内存占用没有关系。你可以这样理解,没问题。——另外,在ECMAScript中,null是一个原始值(Primitive value),这意味着它可以直接在引擎中表达为二进制的存储,真的跟#0很接近了。^^. 而{}是一个对象,它在引擎中表达为一个结构、一个数据块(也就是你认为的放在堆里,其实是不是放在堆里不重要,而且也并不确定)。对象之所以为空白(“{}”称为空白对象Empty objects),是因为它的自有属性表为空,当自有属性表里面没有属性项的时候,它就是空白的了。——你可以重置它的原型,让他表现得有一些属性什么的。因为它毕竟还是一个可操作的、占有引擎中的存储的真实对象。 另外,ECMAScript内部(以及引擎内部的执行逻辑中)其实是把null值理解为“值”的,而不是“对象”。所以ECMAScript的内部方法IsObject(null),是返回false的。
共 2 条评论4 - 晓小东2020-01-03好快,这个专栏结束了,有点舍不得,一个多月来我一直关注老师更新,反复阅听之前章节。体会深思理解,发现如果没有老师带领层层分析JavaScript 最核心那部分设计和概念,真的无缘了解这门语言了,谢谢老师给我们思维上的提升,同时也发现自己对这门语言的理解上,上了一个大大的台阶。在此由衷的感谢,真的感觉,遇到了恩师。
作者回复: 😀+🤝
2 - weineel2020-01-05老师的每一篇都很有深度。我们平时开发中,this 的动态绑定虽然很复杂,但时间长了也能找到规律,仅仅是应用还是没啥问题的。老师要是有时间给我们加个餐,聊聊 this 的深层原理吧。
作者回复: 这个可以有。我考虑一下怎么做到下一个课程吧。这一课结束哒所以也不再有加餐哒。^^.
1 - 大雄不爱吃肉2021-04-01专栏虽然是二十多讲,但是自己看了很久,很多地方反复看反复试。可能最终记住的不是很多,但对js以及语言规范有了深刻的理解,感谢老师这门课,这一门独特的课程我收获颇多,期待老师的下一门课!
作者回复: 多谢多谢。有收获就好。:)
- igetter2020-06-14老师,问一个不太相关的问题: MDN中说,Function()比eval()更高效。这是真的吗?
作者回复: 是的。 Function(x)工作在全局,所以它的作用域层次通常要小于eval(x)。因为作用域(链)的深度小,所以Function()执行要略高效。 如果只是说对代码文本`x`的解析和处理等,两者并没有明显的性能区别。
- K4SHIFZ2020-05-03动态函数创建在规范19.2.1.1.1 Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto). Let realmF be the current Realm Record. Let scope be realmF.[[GlobalEnv]]. Let F be ! OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, scope). Perform SetFunctionName(F, "anonymous")展开
- James2020-02-05老师,我从头听了一遍,有几篇文章听了好几遍,但是感觉完全是云里雾里,没弄懂。我应该怎么办。🤣
作者回复: 补一些基础,再看。建议边读ECMAScript边看。加餐里面我有给地址~找找哇😀
共 2 条评论 - 许童童2020-01-04一路跟着老师走过来,自以为对JavaScript这门语言有一定的了解,才发现只是懂点皮毛,更多深入的知识自己都还没有探究到,感谢老师带我领会了更深刻的JavaScript。之后还是会持续学习,保持对JavaScript的敬畏之心,加油。
作者回复: 能对大家有用就好。我一直以这样的态度来做这件事,那怕能帮助一人,也是好的。多谢你的支持。^^.
- 独钓寒江雪2020-01-03以前有碰到了这样一个疑惑,看了专栏前面的内容,还是不太明白。下面是我的代码,虽然问题比较好解决,但是不太明白: import { message } from 'antd' // 引入AntD组件库中的message export const generateRemark = (skus, message) => {// 这个方法被导出,接收两个参数,其中一个写成了message let remark = '' ...... remark = remark + (message || '')// 使用了message参数 return remark } 当我调用generateRemark(skus, '')时(message传入的是空字符串),返回是[object Object],调试发现,原来message被解析成了antd的message组件了。 是代码环境的问题还是JS底层机制的问题呢?希望老师能帮我解惑,谢谢🙏 最后,也感谢老师的专栏,这样关注底层核心原理的专栏,正是我这种自学前端出道的同学的所需要的。展开
作者回复: 仔细读了几遍你的问题,我觉得这是不可能出现的。但还是小心地写了一个测试来运行了一下,但是还原不了你说的问题。(代码放在后面,你看看是不是这个意思) 我仔细想了一下,非常可疑的事情出来你使用import/export的方法上面。由于NodeJS在一般模式下并不支持ES Module,因此通常我们在应用环境中使用模块的时候,都是用babel来转码的。而早期babel(也包括其它的一些第三方转码器)可能对某些语法支持得不好,所以转出来的结果跟ECMAScript规范并不一致,做不到百分百地兼容。并且,在你的示例中还有一个箭头函数,这个东西在很多转码器和基于转码器的runtime中还是实现得不好的。 所以简单地说,我怀疑是你在应用环境中使用babel或typescript之类的转码器带来的结果。无论如何,ECMAScript的规范中不会有这个问题。如下例: ``` # 运行 > node --experimental-modules t1.mjs // 代码t1.mjs import { generateRemark } from './t2.mjs'; var skus = ''; console.log(generateRemark(skus, '')); // 代码t2.mjs import { message } from './t3.mjs' export const generateRemark = (skus, message) => { let remark = '' // ...... console.log(typeof message, message); remark = remark + (message || '') return remark } // 代码t3.mjs export var message = {}; ```
共 2 条评论