在 ES6模块(Module) 里介绍了ES6中利用关键词export、import使用模块,在 CommonJS的模块规范 介绍了CommonJS的模块规范。本篇主要聊一聊两种模块的加载机制。
more >>ES6模块加载的机制,与CommonJS模块完全不同。
CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。
在 ES6模块(Module) 里介绍了ES6中利用关键词export、import使用模块,在 CommonJS的模块规范 介绍了CommonJS的模块规范。本篇主要聊一聊两种模块的加载机制。
more >>ES6模块加载的机制,与CommonJS模块完全不同。
CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。
上一篇介绍了CommonJS的模块规范, 这一篇主要谈一下ES6的模块
Web开发越来越复杂,需要一个团队分工协作、进度管理、单元测试、持续集成、持续部署…… 社区也开发了很多工具来协助构建这些规模庞大的应用。诸多工具中最核心的非模块系统莫属,在这样一个系统中,你可以通过多个文件和目录来组织你的项目,最重要的是,所有代码都可以按需彼此访问并高效加载。所以JavaScript就这么顺理成章地有了几个知名的模块系统。当然,随之而来的还有几个包管理器,可以用它们安装所有软件以及处理高层次的依赖。如此一来,模块化开发就显得非常重要了,所以本节主要聊一聊JavaScript的模块化开发之CommonJS规范。
理想状态下,Developer只需要实现核心的业务逻辑,其他的可以加载别人已经写好的模块即可,因此JavaScript语言的模块化编程就显得异常重要了。然而,ES6之前JavaScript没有为组织管理代码提供任何方案,甚至没有类(Class)的概念,更不用说模块(Module)了.
模块化管理需要具备:
要通用,则必须要有规范化,因此一系列的标准应运而生。
more >>
在上一节我们聊了 JavaScript原型、原型对象、隐式原型,我们知道
1 | var str = ''; |
上一节我们聊了 JavaScript构造函数(constructor),但是构造函数内部的属性和方法无法被共享。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function Person(name){
this.name = name;
this.group = 'China'; // 我要将group作为实例对象的共有属性
this.getGroup = function() {
console.log('method: ', this.group);
}
}
// 生成两个实例对象
var p1 = new Person('p1');
var p2 = new Person('p2');
// 两个实例对象的group属性都是独立的,修改其中一个不会影响另外一个
p1.group = 'US';
p1.getGroup = function() {
console.log('change the method in p1: ', 'not US, not China');
}
console.log('change the property in p1: ', p1.group);
console.log(p1.getGroup());
console.log('property:', p2.group);
console.log(p2.getGroup());
在上面的代码中,p1和p2对象的group属性和getGroup方法都是独立的,修改其中一个不会影响另外一个,因此每一个实例对象都会拥有其构造函数内部的属性和方法的副本。这无法做到数据共享,也是占用内存极大的浪费资源。
more >>
在大部分的面向对象编程语言中,构造函数是类的一个成员方法,用于类的实例化时初始化对象的。不过在JavaScript里并没有“类”(class)的概念(ES5之后加入了’class’关键词),虽然没有‘类’来创建对象,但是对象仍然可以通过多种方式创建,其中就有构造函数方式,使用new操作符调用构造函数从而生成一个对象实例。
因此我们也可以这么去理解JavaScript中的构造函数,构造函数只是一些使用new操作符调用的函数。他们并不属于某一个类,也不会实例化一个类!
我们来看个Case
1 | // use stric |
上面的代码,当构造函数作为普通函数使用时,我们可以发现一些坑, 构造函数与一个普通函数并无不同,如果你故意不使用new,或忘记用new,都会得到怪异的错误:
JavaScript中构造函数可以有返回值也可以没有。
1.没有返回值的情况像其他传统语言一样,返回实例化的对象
1 | function Person(){ |
2.如果存在返回值则检查其返回值是否为引用类型,如果为非引用类型,如(string,number,boolean,null,undefined),上述几种类型的情况与没有返回值的情况相同,实际返回实例化的对象
1 | function Person(){ |
3.如果存在返回值是引用类型,则实际返回该引用类型
1 | function Person(){ |
对于上面的Person构造函数,当我们执行var person1 = new Person()是,到底发生了什么?MDN上是这么说的 对于var o = new Foo();1
2
3
4//JavaScript 实际上执行的是:
var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);
我们按照MDN上面的过程来理解下var person1 = new Person()的执行过程
JavaScript有九种内置的构造函数:Object(), Function(), Array(), Number(), String(), Boolean(), RegExp(), Date(), Error().当我们需要创建这些值的时候,我们可以自由选择使用字面量或者构造函数。但是相同情况下,字面量对象不仅易读,而且运行速度更快,因为他们可以在解析的时候被优化。所以当你需要使用简单对象的时候就使用字面量吧。
我们先看看在W3school中,关于全局对象的描述:
全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。全局对象不是任何对象的属性,所以它没有名称。
在顶层 JavaScript 代码中,可以用关键字 this 引用全局对象。但通常不必用这种方式引用全局对象,因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来查询。例如,当JavaScript 代码引用 parseInt() 函数时,它引用的是全局对象的 parseInt 属性。全局对象是作用域链的头,还意味着在顶层 JavaScript 代码中声明的所有变量都将成为全局对象的属性。
全局对象只是一个对象,而不是类。既没有构造函数,也无法实例化一个新的全局对象。
javascript中的内置全局对象(独立于宿主环境,ECMAScript中的API中声明的对象)例如Math对象,JSON对象,这个JavaScript自身提供的全局对象的功能包括:
除了JS全局对象,对于运行在浏览器端的JavaScript程序,还有另一个全局对象:window。window全局对象提供了与当前窗口、页面有关的诸多属性与方法。除了这些与浏览器有关的全局属性和方法,window对象还封装了JS全局对象,并向外暴露JS全局对象的属性与接口;因此,当进行浏览器端JavaScript编程时,只需关心window全局对象即可。
对于JavaScript程序中的this,如果this不属于任何function,那么这个this就指代JS全局对象;如果是浏览器端运行的JS程序,那么这个this就指代window全局对象。
如果这个this属于某个function,那么this指代的就是调用该function的对象。若这种情况下function只是一个普通的函数,而不是某个类的方法,那么this的指代存在两种可能:
在上篇 JavaScript执行上下文栈(Execution Context Stack简称ECS) 中,浏览器引擎执行一段JavaScript可执行代码(Executable code)时,会创建对应的执行上下文,执行上下文在创建阶段会创建变量对象,建立作用域,以及确定this的指向。 也就是说对于每一个执行上下文,都有三个重要属性:
本篇主要聊一聊变量对象。
变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。不同的执行上下文下的变量对象稍有不同,所以我们来聊聊全局上下文下的变量对象和函数上下文下的变量对象。
more >>
本文重点讲解JavaScript的执行上下文栈,顺带稍稍提了下执行上下文。
JavaScript语言执行时是自上而下的,JavaScript执行程序的时候,会首先创建一个全局的执行上下文,将其放入栈中,成为栈底。而后每次执行一个函数的时候,都会去创建一个当前函数的执行上下文,然后将其压入栈中,当函数结束或者返回的时候,再从栈中弹出当前函数的执行上下文。
仔细琢磨JavaScript代码是如何执行的的描述,相信我们大家都可以看出一个执行上下文的生命周期通常包含三个发展阶段:创建阶段、代码执行阶段、执行完毕阶段。
JavaScript引擎创建了执行上下文栈来管理执行上下文的顺序
栈stack是数据结构上的概念,用来处理数据的存放方式,特点为LIFO,即后进先出(Last in, first out)。
1 | var a = 10; |
在浏览器中,javascript引擎的工作方式是单线程的。也就是说,某一时刻只有唯一的一个事件是被激活处理的,其它的事件被放入队列中,等待被处理。下面的示例图描述了这样的一个堆栈:
Execution context, Scope chain and JavaScript internals
ECMA-262-3 in detail. Chapter 1. Execution Contexts.
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true