搜索文章
类目归类
搜索到51篇与admin的结果
第二十章 ECMAScript 6 Module
ES6的Class只是面向对象编程的语法糖,升级了ES5的构造函数的原型链继承的写法,并没有解决模块化问题。Module功能就是为了解决这个问题而提出的。历史上,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如Ruby的require、Python的import,甚至就连CSS都有@import,但是JavaScript任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。在ES6之前,社区制定了一些模块加载方案,最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。ES6在语言规格的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。ES6模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时确定这些东西。比如,CommonJS模块就是对象,输入时必须查找对象属性。// CommonJS模块 let ...第十九章 ECMAScript 6 修饰器(Decorator)
类的修饰修饰器(Decorator)是一个函数,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持。修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。function testable(target) { target.isTestable = true; } @testable class MyTestableClass {} console.log(MyTestableClass.isTestable) // true上面代码中,@testable就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。基本上,修饰器的行为就是下面这样。@decorator class A {} // 等同于 class A {} A = decorator(A) || A;也就是说,修饰器本质就是编译时执行的函数。修饰器函数的第一个参数,就是所要修饰的目标类。function testable(target) { // ... }上面代码中,testable函...第十八章 ECMAScript 6 Class
Class基本语法JavaScript语言的传统方法是通过构造函数,定义并生成新对象。下面是一个例子。function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2);上面这种写法跟传统的面向对象语言(比如C++和Java)差异很大,很容易让新学习这门语言的程序员感到困惑。ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用ES6的“类”改写,就是下面这样。//定义类 class Point { constructor(x, y) { this.x = x; t...第十七章 ECMAScript 6 异步操作和Async函数
异步编程对JavaScript语言太重要。Javascript语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可。ES6诞生以前,异步编程的方法,大概有下面四种。回调函数事件监听发布/订阅Promise 对象ES6将JavaScript异步编程带入了一个全新的阶段,ES7的Async函数更是提出了异步编程的终极解决方案。基本概念异步所谓"异步",简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。比如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其他任务,等到操作系统返回文件,再接着执行任务的第二段(处理文件)。这种不连续的执行,就叫做异步。相应地,连续的执行就叫做同步。由于是连续执行,不能插入其他任务,所以操作系统从硬盘读取文件的这段时间,程序只能干等着。回调函数JavaScript语言对异步编程的实现,就是回调函数。所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。它的英语名字callback,直译过来就是"重新...第十六章 ECMAScript 6 Promise对象
Promise的含义Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。Promise对象有以下两个特点。(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rej...第十五章 ECMAScript 6 Generator 函数
简介Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。本章详细介绍Generator函数的语法和API,它的异步编程应用请看《异步操作》一章。Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator();上面代码定义了一个Generator函数hel...第十四章 ECMAScript 6 Iterator和for...of循环
Iterator(遍历器)的概念JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。Iterator的遍历过程是这样的。(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。(3)第二次调用指针对象的next方...第十三章 ECMAScript 6 Set和Map数据结构
SetES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构。var s = new Set(); [2, 3, 5, 4, 5, 2, 2].map(x => s.add(x)); for (let i of s) { console.log(i); } // 2 3 5 4上面代码通过add方法向Set结构加入成员,结果表明Set结构不会添加重复的值。Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。// 例一 var set = new Set([1, 2, 3, 4, 4]); [...set] // [1, 2, 3, 4] // 例二 var items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); items.size // 5 // 例三 function divs () { return [...document.querySelectorAll('div')]; } var set = new Set(divs()...第十二章 ECMAScript 6 二进制数组
二进制数组(ArrayBuffer对象、TypedArray视图和DataView视图)是JavaScript操作二进制数据的一个接口。这些对象早就存在,属于独立的规格(2011年2月发布),ES6将它们纳入了ECMAScript规格,并且增加了新的方法。这个接口的原始设计目的,与WebGL项目有关。所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。文本格式传递一个32位整数,两端的JavaScript脚本与显卡都要进行格式转化,将非常耗时。这时要是存在一种机制,可以像C语言那样,直接操作字节,将4个字节的32位整数,以二进制形式原封不动地送入显卡,脚本的性能就会大幅提升。二进制数组就是在这种背景下诞生的。它很像C语言的数组,允许开发者以数组下标的形式,直接操作内存,大大增强了JavaScript处理二进制数据的能力,使得开发者有可能通过JavaScript与操作系统的原生接口进行二进制通信。二进制数组由三类对象组成。ArrayBuffer对象:代表内存之中的一...第十一章 ECMAScript 6 Proxy和Reflect
Proxy概述Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。var obj = new Proxy({}, { get: function (target, key, receiver) { console.log(`getting ${key}!`); return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { console.log(`setting ${key}!`); return Reflect.set(target, key, value, receiver); } }...第十章 ECMAScript 6 Symbol
概述ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。let s = Symbol(); typeof s // "symbol"上面代码中,变量s就是一个独一无二的值。typeof运算符的结果,表明变量s是Symbol数据类型,而不是字符串之类的其他类...第九章 ECMAScript 6 对象的扩展
属性的简洁表示法ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。var foo = 'bar'; var baz = {foo}; baz // {foo: "bar"} // 等同于 var baz = {foo: foo};上面代码表明,ES6允许在对象之中,只写属性名,不写属性值。这时,属性值等于属性名所代表的变量。下面是另一个例子。function f(x, y) { return {x, y}; } // 等同于 function f(x, y) { return {x: x, y: y}; } f(1, 2) // Object {x: 1, y: 2}除了属性简写,方法也可以简写。var o = { method() { return "Hello!"; } }; // 等同于 var o = { method: function() { return "Hello!"; } };下面是一个实际的例子。var birth = '20...前端前沿观察,Cookie 居然可以这样整了
用 JS 操作 Cookie 其实是很麻烦的,并不存在一个简单的 API 能让我们获取或者设置 Cookie。唯一一个操作 Cookie 的 API 是 document.cookie,但是这句代码使用起来很难受。如果说我们想要获取一个需要的 Cookie,可能得先写这么一个 utils 函数:function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); }但是在 Chrome 87 版本中我们无需再引入这样的代码了,取而代之的是新的 API:cookieStore。这是一个异步的 API,可以很方便地获取设置以及监听 Cookie 的改变。如果你想下载 beta 版本的 Chrome,可以在 此链接 中获取。以下是新内容的介绍。以下是新内容的介绍。获取 Cookie刚才在上文中我们已经了解到在之...V8中JavaScript的内存管理与垃圾回收
前言在一些低级语言中,比如:C语言,我们可以使用malloc()和free()来手动控制内存的分配与释放。但是,在JavaScript里,垃圾回收(Garbage Collection)会自动地帮我们完成内存的分配与释放。尽管如此,我们仍然有必要了解JavaScript中的内存管理。内存生命周期无论使用何种语言,内存的生命周期(Memory Life Cycle)大体一致,可以分为以下三个阶段:分配内存的分配方式分为:静态内存分配动态内存分配使用读写基本变量或对象的属性、传参等操作,都涉及到了内存的使用。释放对于不再使用的内存,应当及时释放。V8内存结构V8的内存结构:正在运行的程序由某些内存表示,这些内存称为常驻集(Resident Set)。栈内存栈用于静态内存分配(Static Memory Allocation),它具有以下特点:操作数据快,因为是在栈顶操作数据必须是静态的,数据大小在编译时是已知的多线程应用程序中,每个线程可以有一个栈堆的内存管理简单,且由操作系统完成栈大小有限,可能发生栈溢出(Stack Overflow)值大小有限制堆内存堆用于动态内存分配(Dyna...JavaScript常见的内存泄漏
前言在阅读这篇博客之前,你或许需要具备一些JavaScript内存管理的知识:V8中JavaScript的内存管理与垃圾回收介绍内存泄露(Memory Leaks):是指应用程序已经不再需要的内存,由于某种原因未返回给操作系统或者空闲内存池(Pool of Free Memory)。内存泄露可能带来的问题:变慢、卡顿、高延迟。内存泄露的主要原因JavaScript内存泄漏的主要原因在于一些不再需要的引用(Unwanted References)。所谓的Unwanted References指的是:有一些内存,其实开发人员已经不再需要了,但是由于某种原因,这些内存仍然被标记并保留在活动根目录树中。Unwanted References就是指对这些内存的引用。在JavaScript上下文中,Unwanted References是一些不再使用的变量,这些变量指向了原本可以释放的一些内存。常见的内存泄露全局变量首先,我们得知道,JavaScript中的全局变量是由根节点(root node)引用的,因此它们在应用程序的整个生命周期中都不会被垃圾回收。场景一:在JavaScript中,如...自适应网站只须一个CSS属性就够了
用一个CSS属性创建一个响应式网站,让我们来看看它是如何做到的。以这个模板为例,没有应用css属性。使用 clamp() CSS函数,我们可以创建仅具有一个属性的响应式网站。现在添加魔术CSSclamp(minimum, preferred, maximum);在这里!你已经完成了说明clamp() 的工作原理是“夹紧”或限制一个灵活的值,使其处于最小和最大范围之间。使用方法如下:minimum 最小值:例如 16pxflexible 弹性值:例如 5vwmaximum 最大值:例如 34pxh1 { font-size: clamp(16px, 5vw, 34px); }在此示例中,仅当该值大于 16px 且小于 34px 时,h1 字体大小值将为视口宽度的 5%。例如,如果你的视口宽度是 300px,你的 5vw 值将等于 15px,但是,你将该字体大小值限制为最小 16px,因此这就是将要发生的情况。另一方面,如果你的视口宽度为 1400px,则 5vw 将高达 70px!但幸运的是,你将该最大值限制为 34px,因此它不会超过该值。我可以为此模板添加此代码...img...vue组件间通信六种方式
组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。本文总结了vue组件间通信的几种方式,如props、emit/on、vuex、parent/children和provide/inject等,以通俗易懂的实例讲述这其中的差别及使用场景。如上图所示,A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代)。针对不同的使用场景,如何选择行之有效的通信方式?这是我们所要探讨的主题。本文总结了vue组件间通信的几种方式,如props、$emit/$on、vuex、$parent/$children、$attrs/$listeners和provide/inject,以通俗易懂的实例讲述这其中的差别及使用场景,希望对小伙伴有些许帮助。方法一、props/$emit父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。父组件向子组件传值接下来我们通过一个例子,说明父组件如何向子组件传递值:在子组件Users....JavaScript之async/await实现
前言yield在平时使用的是真的真的非常非常的少,他的出现频率对于大多人来说不亚于在Virtual Studio中随便打一个字符然后出现一个超级长的自动补全内容,而且这个超长自动补全恰好是你需要的内容一样的低概率。但是,如果对于一些特殊情况,而且你恰好有适用场景,那么这个yield可以说是一把利剑。而Babel中,把async转化成原生代码的插件transform-async-to-generator也是利用了yield进行。所以,在理解await之前,必须要先理解yield。YIELD首先我们要理解,yield是什么,有什么用,能干什么,怎么才能去获取Promise的控制权。想要了解这些问题,最好的办法就是看个例子。let ge = (function* (){ let c = yield 5 // ge.next()=> console.log(c)// =>15 })() console.log(ge.next()) //=>{ value: 5, done: false } console.log(ge.next(15)) //=>...