JavaScript进阶

一、ES6基础

1. ECMAScript 6 简介

ECMAScript(ES6) 是JavaScript语言的下一代标准,已经在2015年6月正式发布了;在 JavaScript 的基础上做了重大的更新,提供了更优雅的语法和特性。

ECMAScript 和 JavaScript 的关系

ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现。日常场合,这两个词是可以互换的。那为什么不叫 JavaScript 为换名字了呢?原因如下:

  1. 商标,1996年11月,JavaScript的创造者Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这种语言能够成为国际标准。根据授权协议,只有Netscape公司(Javascript 的创造者)可以合法地使用JavaScript这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。
  2. 想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。

2. ES6 新特性

let 和 const

ES6提供了两种新的声明变量的方式:let 和 const。其中let 和 const 相比于 var 声明的变量有块作用域,let 和 const 只在于当前的块作用域中有效。而 var 声明的变量是在函数作用域内有效。
没有块级作用域,会出现很多不合理的情况。
1、内层变量可能会覆盖外层变量。例如:

var n = 5;      
function f1() {
  console.log(n); 
  if (true) {
    var n = 10;
  }
}
f1();  //undefined

发生了变量提升,导致内层的n变量覆盖了外层的n变量。 而块级作用域不存在变量提升 ,let所声明的变量一定要在声明后使用,否则就会报错。上述代码如果使用let进行声明,则会报错。

let n = 5;      
function f1() {
  console.log(n); 
  if (true) {
    let n = 10;
  }
}
f1();  //报错

ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。这样可以减少运行时的错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
2、用来计数的循环变量会泄露为全局变量。例如下面的代码如果使用var,最后输出的是10。

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

其中变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。
如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

变量的解构赋值

按照一定的模式,从数组或对象中提取值,对变量进行赋值的操作。

数组的解构

var [a,b,c] = [1,2,3] // 结果 a=1 b=2 c=3
var [a,[b,c]] = [1,[2,3]] // 结果 a=1 b=2 c=3

//解构不成功
var [a] = [];  // a = undefined   
var [a, b] = [1]; //a=1 b=undefined

//不完全解构
var [a] = [1,2]; //a=1

//默认值
var [a=1] = [] //a=1

如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错

let [a] = 1;
let [a] = false;
let [a] = NaN;
let [a] = undefined;
let [a] = null;
let [a] = {};

对象的解构

var { b, a } = { a: "aaa", b: "bbb" };
a // "aaa"
b // "bbb"

字符串拓展

模版字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串(类似 pre 标签的作用),或者在字符串中嵌入变量。

// 普通字符串 想要换行需要加上 '\n'
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

// 字符串中嵌入变量
var name = "ac", time = "today";
`Hello ${name}, how are you ${time}?` // Hello ac, how are you today? 

rest 展开运算符

function example(...values){
    console.log(values)// console: [1,2,3,4]
}

example(1,2,3,4) 


var a = [1,2,3]

var b = [...a,4,5,6] //b = [1,2,3,4,5,6]

箭头函数

ES6 提供了新的方式 => 来定义函数

var func = parm => parm
等同于
var func = function (parm){
    return parm
}

如果函数没有参数或有多个参数,那么:

var func = () => //some code
等同于
var func = function (){
    some code
}

var func = (parm1,parm2) => //some code
等同于
var func = function (parm1,parm2){
    some code
}

如果箭头函数的函数体只包含一行代码,则可以不需要写大括号以及 return 语句返回(如果有返回值)

var sum = (num1,num2) => num1+num2
等同于
var sum = (num1,num2) => {return num1+num2}
等同于
var sum = function(num1,num2){return num1+num2}

箭头函数使得表达更加简洁

[1,2,3].map( item=> 2 * item)
等同于
[1,2,3].map(function(item){
    return item * 2
})

[1,3,2].sort((a,b) => a - b)

二、面向对象基础

什么是面向对象编程

  • 把一组数据结构和处理它们的方法组成对象(Object);
  • 把相同行为的对象归纳为类(Class), 通过类的封装(encapsulation)隐藏内部细节;
  • 通过继承(inheritance)实现类的特化(specializetion)/泛化(generalization),;
  • 通过多态(polymorphism)实现基于对象类型的动态分派。

面向对象的好处?

  1. 接近人的思维,符合人类对现实世界的认知;
  2. 封装特性可以使开发者不必在意内部的具体实现,更方便互相协作;
  3. 继承特性可以减少代码冗余,实现代码复用;
  4. 多态特性令子类相比父类有不同的行为,这是非常接近现实的;

封装

1、字面量模式

var Cat = {
 name : '',
 color : ''
} 

这样的方法的缺点是如果多生成几个实例,写起来就非常麻烦。

2、工厂模式

function Cat(name,color) {
 return {
    name:name,
    color:color  
  }
}

这样写可以解决生成多个实例的问题,比较方便,但是调用之后实例的类型只是一个普通的对象,而不是一个具体的类型。

3、构造函数模式

function Cat(name,color){
   this.name=name;
   this.color=color;
   this.eat = function(){};
}
var cat1 = new Cat("big","yellow");
var cat2 = new Cat("small","black");

这样解决了实例不为一个特定类型的问题,使用instanceof运算符可以验证原型对象与实例对象之间的关系。

console.log(cat1 instanceof Cat); //true

但是这样有一个问题是:每一次生成一个实例,都会产生一个新的内容一模一样的方法,是重复的部分,会多占用内存空间。

4、原型模式

function Cat(){ }
Cat.prototype = {  
   type='animal';
   this.eat = function(){};
}

使用原型模式所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。但是对任何一个实例的操作会影响到所有的实例。

5、混合模式

function Cat(name,color){
  this.name = name;
  this.color = color;
}
Cat.prototype.type = "animal";
Cat.prototype.eat = function(){};

需要变化的属性使用构造函数定义,不变的属性和方法使用原型来定义。但是这种写法不够美观。

6、类

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。新的class写法可以让对象原型的写法更加清晰、更像面向对象编程的语法。

class Cat(){
  constructor(name,color) {
    this.name = name;
    this.color = color;
  }
  eat() {}
}

继承

Class 可以通过extends关键字实现继承,例如定义了一个ColorPoint类,该类通过extends关键字,继承了Point类的所有属性和方法。

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
class ColorPoint extends Point {
}

super关键字表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }
  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容