你应该理解的编程概念:上下文

前言

张飞:“俺也一样!”

正文

概念:是什么

上下文定义:位于关键词前部或后部的词句或文字。它是关键词所处的语言环境,影响关键词的含义。通过阅读上下文,有助于理解和鉴别某关键词所具有的准确含义和用法,判断文献是否相关。

---《图书馆·情报与文献学名词》

上下文切换(context switch)定义:根据某种条件,暂停当前进程或线程的执行,保护当前进程或线程的现场,恢复另一个进程或线程的现场,转而执行该进程或线程的过程。

---《计算机科学技术名词 》 (第三版)

因此,我们得知:上下文,即语境,语意.

那么,编程中的上下文(context)指的是什么呢?

总的来说,编程上下文共有三个类别。

一个是业务上的上下文(基础实体)。

譬如说:某个后台系统,登录实体为个人,所以功能都是以个人为基准来触发的。但有一天,业务需求,集体账号也可以登录,该账号登录后要获取到集体所有个人的信息,那在触发功能的时候,原先以个人为基准触发的功能就需要兼容到集体账号。这个过程就是的业务上下文变更的操作。
业务上下文笼统的说就是业务操作所对应的基础单位(实体),那如果业务上下文需要变更,那需要更改的代码以及需要做的回归测试是很庞杂的。所以业务上下文变更需要慎之又慎。

另一个是运行程序的上下文(Environment)。

大家应该对一句话有印象:(进程/线程)上下文切换开销很大。这里的上下文一般指的就是运行程序的上下文。

一个应用程序有可能由多个不同的编程语言文件组成。
比如web网页,由html,css,js文件组成,每个编程文件都有自己的上下文,所以要如何将html中的数据传递到js文件中呢?这便是 data-* 元素属性的目的了。

data-* 全局属性 是一类被称为自定义数据属性的属性,它赋予我们在所有 HTML 元素上嵌入自定义数据属性的能力,并可以通过脚本在 HTML 与 DOM 表现之间进行 专有数据的交换
通过添加 data-* 属性,即使是普通的 HTML 元素也能变成相当复杂且强大的编程对象。

又比如原生应用的webview页面时,会处理webview页面和原生应用之间的通信问题。一般地,都是原生应用在window对象上挂载一系列方法,JS代码可以通过调用这些方法从而触发原生应用的功能。该过程通信慢,响应不够快速。所以社区产出了react-native模块来优化通信问题。这里的通信问题就是进程上下文切换开销大的缘故。

对于前端开发者而言,运行程序的上下文也包含页面上下文
前端开发者开发的程序都是呈现在页面(web页面,客户端页面,传统GUI程序所表现的界面和对应的弹窗)上的,页面间切换就是路由要做的事情。基本上,不同的页面运行不同的业务逻辑。在页面跳转时,可能后一个页面需要前一个页面中的某些业务数据,但由于页面上下文已变更,通常,需要通过一些手段来将业务数据从前一个页面传递到后一个页面。web页面总的处理方式有如下几种:

  1. 通过url的search属性将小量数据传递过去
  2. 将业务数据存储到所有页面都能访问到的环境,譬如说全局对象。

不同的web页面有不同的使用全局对象的方法,如下:

  1. SPA工程下的不同页面,一般使用状态库reduxVuex, etc,来解决数据访问问题,也可使用url的search属性。
  2. 同域名下的不同页面,可以使用sessionStoragelocalStorage, cookie对象,也可使用url的search属性。
  3. 不同域名下的页面,只能使用url的search属性来传参

说到这里,不同域名下的页面的跳转又关联到一个编程概念:数据持久化,从A域名下的页面跳到B域名下的页面,又回到A域名下原先的页面,windowsessionStorage对象,当然上面的状态库也都是最新的,之前的状态是没有的。那如果要在这过程中保留A域名下页面的某些数据,应该怎么做呢?这就是数据持久化要解决的问题。答案是将数据保存到localStorage对象中,小量数据比如token可以保存到cookie对象上。

还有一个是编程语言中方法/类所在的上下文(作用域)。

方法上下文可以理解为方法所在的作用域。类亦如此。还有一些比较特殊的概念实际上也是和方法上下文相关。比如worker语言特性中,需要监听message事件,这实质上,就是在当前上下文监听另一个上下文的状态。再比如回调函数。实际上是因为上下文变更后,对原有上下文访问的一种编程手段。从这个角度看,闭包实质上也是对上下文的一种操作手段:返回一个函数,该函数在当前上下文可以操作闭包上的上下文。

方法/类所在的上下文实践

既然有这么多上下文,我们可以做些什么?

第一,二种上下文,实际上离我们平日里编写代码有点远。所以我们着重关注第三类上下文。

在JS编程语言中,有如下语法可以操作上下文:

  1. bind, apply, call
  2. 箭头函数
  3. 回调函数/事件监听

bind, apply, call方法的调用很相似,只有一些细微差别,它们的第一个参数都是调用函数的this指向,其余参数将作为新函数的参数,供调用时使用。

方法是否立即执行其余参数
bind否,该方法创建一个新的函数作为新函数的参数
apply只有两个参数,第一个参数作为新函数调用时的this指向,第二个参数为数组(或类数组对象),数组中的成员对象将作为新函数的参数
call参数没有限制,第一个参数作为新函数调用时的this指向,其余参数将作为新函数的参数

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

--- MDN 箭头函数

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this ,因此,当箭头函数被创建的时候,它的函数上下文就已经是被固定的了。通过 bind()call()apply() 方法也是不能改变的哦。

从上下文的角度来看,回调函数/事件监听基本上都是一个逻辑,将其他位置上下文所在的数据通过事件,传递给当前的回调函数。以达到上下文切换的目的。

参考链接

  1. 上下文_百度百科
  2. 编程中什么是「Context(上下文)」?
  3. JavaScript 标准内置对象: Function
  4. data-*全局属性
posted @ 2021-01-07 16:08  西河  阅读(201)  评论(0编辑  收藏  举报