Javascript引用与绑定…什么';有什么区别?
我最近在凯尔·辛普森(Kyle Simpson)的《你不知道JS:ES6》中读到了以下内容 “[ES6模块导出]到内部模块定义中标识符的实际绑定(几乎像指针)。” 我的困惑是这些绑定与引用有什么不同 我知道JS中的引用仅适用于非基本类型(如对象),因此Javascript引用与绑定…什么';有什么区别?,javascript,reference,ecmascript-6,es6-modules,Javascript,Reference,Ecmascript 6,Es6 Modules,我最近在凯尔·辛普森(Kyle Simpson)的《你不知道JS:ES6》中读到了以下内容 “[ES6模块导出]到内部模块定义中标识符的实际绑定(几乎像指针)。” 我的困惑是这些绑定与引用有什么不同 我知道JS中的引用仅适用于非基本类型(如对象),因此 let object1 = {a: 1}; let object2 = object1; object1和object2现在指的是同一个对象(它们都是对同一对象的引用)。 如果我将属性添加到object2,我也将属性添加到object1 obj
let object1 = {a: 1};
let object2 = object1;
object1
和object2
现在指的是同一个对象(它们都是对同一对象的引用)。如果我将属性添加到
object2
,我也将属性添加到object1
object2.b = 2;
console.log(object1.b); // 2
我可以看到,绑定可以应用于基本类型和非基本类型
// foo.js
export let count = 1;
export function incrementCount() { count++; }
// bar.js
import {count, incrementCount} from foo;
console.log(count); // 1
incrementCount();
console.log(count); // 2
除了原语值也可以共享绑定(而引用仅限于非原语类型)之外,绑定是否与引用类似
我觉得我在这里遗漏了什么…效果不是特定于原始值的,它就像访问对象上的属性一样 例如:
let foo = {a: 1};
let bar = foo;
foo = {b: 2};
console.log(bar); // {a: 1}
但是:
所以bar的a
与foo的a
绑定在一起,并且具有完全相同的值,无论是原语还是引用。a是“名称所指内容”的一个非常通用的术语。作用域中的每个标识符都绑定到某个对象。通常,它们解析为可变环境中的变量(中的存储插槽),但也有例外情况(例如,带有的或全局对象)
是指向某种结构的指针的术语。例如,对象被称为“”,因为它们引用具有标识的可变属性容器
ES6模块现在引入了一种新的绑定类型,这在以前是未知的。它不是一个普通的变量,而是对另一个变量的引用——从另一个模块导出的变量。如果模块变量更改,这将通过导入反映出来-它们都指向同一个环境记录槽。导出
声明添加从本地名称到中名称的映射,而导入
声明添加从相应模块接口中的名称到本地名称的映射。当一个模块被实例化时,它指向与导出模块中的本地绑定相同的环境。尽管@Bergi给出了很好的回答,但我想为背景知识较少的用户提供更详细的回答
名称绑定
名称绑定是根据Javascript的词法范围规则将标识符与命名内存块(变量)关联起来。需要名称绑定,因为标识符可以存在于不同的作用域中,因此可用于不同的变量:
函数f(){let x=0}
设x=1;
{设x=2}
{设x=3;
{设x=4;
{console.log(x)}//日志4
}
}“除了原语值可以共享绑定而不能共享引用之外,绑定是否与引用类似?”——另外,它是只读的。仅供参考,您的示例
让a=1;导出默认值a
不导出a
的实时版本,您希望让a=1;导出{a作为默认值}代码>以使其工作<代码>导出默认值a代码>在此上下文中与导出默认值4+5没有区别代码>,将计算表达式并为其创建您无权访问的绑定。导出默认X的唯一情况
确实为声明创建了活动绑定,例如导出默认类a{}
@loganfsmyth:你确定吗?我的印象是export default a
和export{a as default}
是等价的;导出默认值a相当于设a=1;让_secret=a;导出{u secret作为默认值}代码>。谢谢@loganfsmyth。将编辑问题以反映这一点。实际上,绑定将标识符与存储位置(包含值)相关联,而不是与值本身相关联。否则,输入一个值就行不通了。当你说默认的导出是不共享的,这真的很让人困惑。尤其是在您的示例中,o
是一个始终共享的对象(参考值)。@Bergi关于您的第二条评论:但不会是export default o
*default*
的本地名称,因此无法从模块内访问创建的绑定?因此,从“模块”导入o;o、 foo=“bar”
不会影响模块中的o
。是的,这样一个默认导出的绑定是不可访问的,因此您不能重新分配其他内容,但所有内容都在模块之间共享(这就是整点:导入模块中的o
引用与*default*
相同的存储位置)-而且,正如答案的第二部分所解释的,对象始终是共享的,即使它们包含不同的变量(导出模块中的o
和*default*
)。
// foo.js
let a = {a: 1};
function mutateA() {
a = {b: 2};
}
export a;
export mutateA;
// bar.js
import {a, mutateA} from foo;
console.log(a); // {a: 1}
mutateA();
console.log(a); // {b: 2}