# JS迷宫(一)#

227 阅读9分钟

JS迷宫(一)#

闭包与“类”

作为一个C过程编程,和类继承背景的程序员,不得不说我对于JS这种函数内嵌套函数,又返回函数的语法一开始感到不适应。细细分析后,这种所谓闭包——内嵌函数并返回一个函数或对象——只是JS版的类定义。

`闭包函数:返回函数对象的函数

闭包的关键表象是,函数返回函数。返回「简单值」的函数只是普通函数,而返回「函数对象」的函数,其实是一个对象的构造函数。JS对保存对象,和简单值的方式是不一样的,这才有了闭包功能。

`闭包用途

任务有私有计算数据的计算任务

JS迷宫(二)# 闭包与嵌套函数

闭包的涵义大概明白,然而实践上怎么用呢?闭包常出现在嵌套函数,函数嵌套是个很强烈的信号,外层函数不仅仅是普通的指令计算(内层才是),而是函数级计算,外层函数就是类构造函数?!

JS迷宫(三)# 函数的局部表达?

JS函数有全局声明、局部表达式,和匿名等多种形式,可被调用或传递。为啥会有如此设计呢?其实函数多样取决于计算任务的多样性(函数的质和函数间协作方式/ 计算任务的分割方式),而非设计者的一种技术创造。全局函数表明计算任务的通用性,可被整支程序多处“调用”,相对的表达式和匿名函数的计算任务相对的特殊具体,和具有动态性。全局声明式函数好比类或子类,表达式函数则是对象实例。

此人抓到一个关键的闭包表象。调用时作用域不同于定义时的作用域,其实就是对象实例(计算任务)的创建。这些对象任务有独立的计算数据,和计算操作(子任务),才有了闭包的概念。

从技术细节解释闭包,是拙劣的,既不好懂,也解释不清楚全面

#函数传递与计算值传递# 函数传递是什么意思呢?函数子程序被调用时传递的变量是【计算值】,是计算任务一步或多步计算步骤的构成元素,而函数传递的是整个【计算任务】,函数传递的是一段代码区的起始地址,【函数】是被调用的,而【值】是被evaluate,是两种不同层级的程序设计。明白函数传递其实就是分割大计算任务,和增加程序动态性的技术,能更好的使用函数传递。

JS迷宫(四)# 闭包与JS应对应用计算的设计

闭包是什么,这个问题,专家各种解释很技术,和表面。例如最常见是指,内嵌函数(nested func)中,内函数指令能够访问外函数的变量,仿佛外变量是内函数的“私有成员”。有专家指出了原因是,JS编译器实现一种特殊“作用域链”(scope chain)。无论是哪种解释,在我看来,都是很有“实践派”的味道,连《犀牛书》也说内嵌函数的作用域规则“很有趣”,仿佛是JS设计者无意中发现这种“有趣”特性。我作为理论派却有别样的解释,或许更“有趣”。其实,常见的闭包例子只用一个内函数,和一个变量来解释是不得法的,省略太多难以揭示实质。试想下,为什么要将内函数使用的变量放到外边来?直接传给它(或者放到里面)不就行了?!单个内函数和变量不能很好表现二者的在计算任务上的独立性和相关性。所以内嵌函数实质内嵌的是一个大任务不同部分(变量数据可以看成没有指令的任务),内嵌两个以上的函数,他们通过外变量进行计算协作。JS有过程函数的“血统”,但是为适应应用计算代码复用的计算动态性潮流,引入“闭包”这种OO模拟机制。

JS迷宫(五)#“我是谁我在哪里?”与JS动态性

JS有两个轻API(或许还有)揭示了JS面对的计算任务的动态,一个是typeof,一个是this。由于动态,对象常常不确定值(类型),例如空对象null,有没有值(undefined);函数可以创建和传递,函数依赖的上下文也会变化。typeof就是变量问我是谁,this就是函数问我在哪里。

JS迷宫(六)#this关键字与JS函数的通用性

JS函数作为一个计算任务的模板,有一定通用性,需要具体参数值进行具体化;然而,JS函数能被传递,它的抽象通用性超越参数值一种,还有执行的环境(context),这就是this。流行的【对象函数代码观】其实很难解释清楚this的现象,【计算任务代码观】则可以。函数可抽象成很通用计算任务,作为其他大的计算任务的组成部分。

JS迷宫(七)#

JS有两个耐人寻味的关键字,一个是Function,一个是new。这两者背后隐藏的JS重要秘密。函数对象为“函数作为一等公民”提供支持,函数可以作为“值”创建和传递,为JS的动态性提供了技术。new是对象实例的“赋值”,他和特殊的构造函数一起,为JS实现OO(计算任务继承复用)提供技术。

函数传递除了为JS提供动态性功能,还有函数式编程,就是,函数是指令语句的抽象,函数对象可对函数本身进一步抽象。

JS迷宫(八)#

理解JS代码有一些基点,第一,代码调用,就是代码是怎么被执行的;第二,代码干了些什么。一般常规程序调用点是加载,而作为交互编程,JS调用点是交互事件,除了加载,还有点击、定时和异步完成等多种由浏览器代理触发的执行点;第二,代码任务,大致分为三类——函数对象的定义(function/var),函数对象的创建(new/字面),函数对象的使用(call/apply)计算。它们的关系是,计算任务执行前先创建(执行环境),创建(赋值)计算任务前先定义。

JS迷宫(九)# 对象作用域

“JS函数能产生词法作用域”,这是表面的。作用域的本质超越了语言语法,是计算任务层次化的本质,JS在语法上支持函数机制,和函数内嵌函数,背后意味着对对象作用域的控制。通过这种控制实现【函数】和【内嵌函数】的逻辑涵义——计算子任务,和复杂动态计算任务。简单的,实现子程序分割的函数功能决定局部作用域的技术,是概念(计算任务)在先,技术实现在后(对象作用域控制规则)。

JS迷宫(十)# 编程范式与计算任务种类

为什么JS通过函数对象等特性支持弱类型、函数传递、闭包类封装、原型继承、函数式编程等多种范式?如果JS面对的计算任务和C一样,静态可预期,JS就没必要支持弱类型,同理其他特性也一样,是计算任务的特性需要决定JS的多种特性的支持,不能弄反。更重要的是,对不同计算任务的特性(例如异步事件的处理)的了解,对掌握JS很有裨益。意义提供强劲动力。

JS迷宫(十一)# 函数和对象的多重角色

JS里,函数和对象都有多重用法。常规的静态使用函数,函数只是个简单静态计算任务抽象工具;而将函数及其相关计算数据绑定为闭包,函数可以扑捉动态计算;而当函数可以传递时,可以实现高阶函数。对象可以用来表达任意值组合(相对于简单类型只有单值,数组值不任意),通过对象属性(property)使用这些值。对象也是实现原型式继承的基础设施。

JS迷宫#(十二)值与效应

简单类型是简单值,对象是复合值,函数对象是另一种值;使用【值】的语句产生效应(side effect),单一语句产生简单效应(有多少种?),函数产生复合效应,函数传递产生另一种效应。

JS迷宫#(十三)JS对传统静态编程的超越

“每一个对象都有一个原型(父类)”,就像每一个函数都有一个运行环境(this)一样。简单创建时,例如字面创建,prototype和this都是默认当前的。当然JS也为灵活性提供了Object.create(prototype)和Function.apply(this),自定义“父类”和函数上下文。原型继承和函数上下文是JS超越静态计算型编程,实现动态应用编程的发展特性。

#简单变量赋值产生的效应# 一个空地上的漂亮吊球是“无用”的,但是当移入比赛场地,则可能引起精彩的喝彩声。同理,JS变量数据、函数方法和计算对象被“移入”应用上下文,才会有用,和精彩。JS核心只有计算意义,没有应用意义,这是运行宿主(例如浏览器)所赋予的。ps.犀牛书的内容组织很先进。

JS迷宫# (十四) JS核心及核心之外

window对象既是client端对象,也是JS对象。相对于基本功的JS核心(编程构件),我要开始转向应用端的特性的学习。而正是这种转向,对比出JS核心深层意义。面包师傅的价值是做出一个个可以吃的面包,产生一种切实的社会效应。同理,编程者通过创建JS对象,更新对象变量赋值等来产生应用效应。而这些具体价值的效应大都在JS核心之外,由应用客户端环境定义。JS核心提供很多基础计算工具。但计算的具体意义由脚本宿主环境提供。