C++JavaScript之一起(三)

JavaScript之旅(三)


三、函数

每当JavaScript中,定义函数的法门如下:

function abs(x) {

return …;
}
如没return,返回结果吧undefined。

其次种概念函数的法如下:

var abs = function (x) {
return …;
};
于这种办法下,function(x){…}是一个匿名函数,它并未函数称呼。但是,这个匿名函数赋值给了变量abs,通过变量abs就可以调用该函数。注意这种办法随总体语法需要以函数体末尾加一个;,表示赋值语句结束。
其三种概念函数的主意:自实施函数
(function(arg){
console.log(arg);
})(‘123’);
这种措施下,函数在概念的以就执行了,常用来多个js文件时包装自身还是闭包。说白了,就是得到同样块命名空间,不影响别人或者给他人影响。

JavaScript允许传入任意个参数而非影响调用,因此传出的参数比定义之参数多或者掉还并未问题。这同其他的言语打不平等,个人认为可能是计划时比短,先天不足的题材。

arguments关键字

主要字arguments只于函数内部由作用,并且永远对当前函数的调用者传入的有参数。arguments类似Array但它不是一个Array。
利用arguments,可以博得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是得以用到参数的值。
实际arguments最常用来判断传入参数的个数。

rest参数

鉴于JavaScript函数允许收取任意个参数,于是只能为此arguments来取具有参数。为了拿走除了已经定义参数之外的参数,ES6业内引入了rest参数。

function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1);
// 结果:
// a = 1
// b = undefined
// Array []

rest参数只能写在最终,前面用…标识,从运行结果可知,传入的参数先绑定a、b,多余的参数为数组形式提交变量rest,所以,不再要arguments我们就算收获了全方位参数。

只是,这些参数的风味,个人建议并非动。因为其那么点好之救助,远较其或许带来的风险和分神而稍稍。请尽可能利用正规及规范的参数传递方法,让他人能看明白,让程序会看明白,而未是炫耀那些无聊之艺。

当函数被查封装于目标被,就称为该对象的办法。
比如:

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};
xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

每当艺术中,this是一个特殊变量,它始终本着当前目标,也就是xiaoming这个变量。所以,this.birth可以用到xiaoming的birth属性。

而是出于js设计之原状弱点,在语言的头就有多相差或考虑次的地方,关于艺术的调用有各种坑,因此无是怪有必不可少的景况下,请以最基本的语法,不要投有冷的技艺。如果你免要是,请研究apply和call方法,或者js的装饰器。

季、函数进阶

4.1 map()

类似python的map函数。

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

map()传入的参数是pow,即函数对象自我。

4.2 reduce()

Array的reduce()把一个函数作用在是Array的[x1,x2,x3…]达,这个函数必须接受两只参数,reduce()把结果连续与排的生一个素做累积计算,其意义即使是:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
如对一个Array求和,就足以据此reduce实现:

var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x + y;
}); // 25

4.3 filter()

用于把Array的某些因素过滤掉,然后返回剩下的要素。与python是均等样的。
与map()类似,Array的filter()也吸收一个函数。和map()不同的凡,filter()把传播的函数依次作用为每个元素,然后根据返回值是true还是false决定封存还是丢该因素。
譬如,在一个Array中,删掉偶数,只保留奇数,可以这么写:

var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
    return x % 2 !== 0;
});
r; // [1, 5, 9, 15]

4.4 sort()

Array的sort()方法默认把持有因素先易为String再排序
sort()方法会直接指向Array进行改动,它回到的结果仍是当前Array
sort()方法为是一个高阶函数,它还可接过一个比较函数来实现自定义的排序。
倘要论数字大小排序,可以这么写:

var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
}); // [1, 2, 10, 20]

4.5 闭包

每当未曾class机制,只有函数的语言里,借助闭包,同样好打包一个私房变量。我们用JavaScript创建一个计数器:

'use strict';
function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}

她因此起像这么:

var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3

var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13

于返回的对象吃,实现了一个闭包,该闭包携带了片变量x,并且,从表代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且她的状态好了对外隐藏起来。

闭包还可把多参数的函数变成单参数的函数。例如,要计算xy可以用Math.pow(x,
y)函数,不过考虑到常计算x2还是x3,我们得使用闭包创建新的函数pow2和pow3:

function make_pow(n) {
    return function (x) {
        return Math.pow(x, n);
    }
}

// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);

pow2(5); // 25
pow3(7); // 343

五、js的作用域

1. “JavaScript中无块级作用域”

在Java或C#遭逢是块级作用域,即:大括号啊是一个作用域。但是于JavaScript和python中莫块级作用域。

但!但是!JavaScript6备受新引入了let关键字,用于指定变量属于块级作用域。也就是说以后或会见发生块级作用域了。

2. JavaScript用到函数作用域

在JavaScript中每个函数作为一个作用域,在函数外部无法访问函数内部的变量。

function Main(){
    var innerValue = 'seven';
}
Main();
console.log(innerValue);
// 报错:Uncaught ReferenceError: innerValue is not defined

3. JavaScript底作用域链

是因为JavaScript中的每个函数作为一个作用域,如果起函数嵌套函数,则就是见面面世图域链。

xo = 'alex';
function Func(){
    var xo = "seven";
    function inner(){
        var xo = 'alvin';
        console.log(xo);
    }
    inner();
}
Func();

如果上述代码则出现三单作用域组成的打算域链,如果起图域链后,那么寻找变量时候便会起顺序,对于上述实例:
当尽console.log(xo)时,其找顺序也因作用域链从外到外的预先级寻找,如果内层没有就逐步前行找,直到没找到抛出异常。

4. JavaScript之意向域链执行前已开立

JavaScript的作用域在给执行前都创办,日后重夺实践时就待以作用域链去寻找即可。

例子1:

xo = 'alex';
function Func(){
    var xo = "seven";
    function inner(){
        console.log(xo);
    }
    return inner;
}
var ret = Func();
ret();
// 输出结果: seven

上述代码,在函数被调用之前作用域链已经有:
大局意图域 -> Func函数作用域 -> inner函数作用域
当尽【ret();】时,由于其代指的凡inner函数,此函数的意图域链在推行前曾给定义为:全局意图域
-> Func函数作用域 ->
inner函数作用域,所以,在实施【ret();】时,会基于已在的意向域链去追寻变量。

例子2:

xo = 'alex';
function Func(){
    var xo = "eirc";
    function inner(){
        console.log(xo);
    }
    xo = 'seven';
    return inner;
}
var ret = Func();
ret();
// 输出结果: seven

上述代码和示例一的目的相同,也是强调在函数被调用之前作用域链已经在:
全局意图域 -> Func函数作用域 -> inner函数作用域
不等之常常,在履【var ret = Func();】时,Func作用域中之xo变量的值都由
“eric” 被重置为 “seven”,所以后来再行履行【ret();】时,就不得不找到“seven”。

例子3:

xo = 'alex';<br>
function Bar(){
    console.log(xo);
}
function Func(){
    var xo = "seven";

    return Bar;
}
var ret = Func();
ret();
// 输出结果: alex

上述代码,在函数被实施前曾经创办了片漫漫作用域链:
全局意图域 -> Bar函数作用域
大局意图域 -> Func函数作用域
当执行【ret();】时,ret代指的Bar函数,而Bar函数的来意域链已经是:全局意图域
-> Bar函数作用域,所以,执行时会见依据已在的企图域链去摸。

5.声明提早

以JavaScript中如果不创造变量,直接去采用,则报错:
console.log(xxoo);
// 报错:Uncaught ReferenceError: xxoo is not defined
JavaScript中若创建值如果无赋值,则该值为 undefined,如:
var xxoo;
console.log(xxoo);
// 输出:undefined
以函数内而如此形容:
function Foo(){
console.log(xo);
var xo = ‘seven’;
}
Foo();
// 输出:undefined
上述代码,不报错而是输出undefined,其故是:JavaScript的函数在叫实施前,会拿里面的变量全部声明,而不赋值。所以,相当给上述实例中,函数在“预编译”时,已经实施了varxo;所以上述代码中输出的凡undefined。

其实,JavaScript默认有一个大局对象window,全局作用域的变量实际上为绑定到window的一个属性。
JavaScript实际上就发生一个大局作用域。任何变量(函数也即变量),如果无当此时此刻函数作用域中找到,就见面继续于上摸索,最后使以大局作用域中呢远非找到,则报ReferenceError错误。
全局变量会绑定到window上,不同的JavaScript文件要以了一如既往之全局变量,或者定义了千篇一律名字的顶层函数,都见面导致命名冲突,并且充分不便被察觉。
缩减冲之一个方是拿好的有变量和函数全部绑定到一个全局变量中。把团结的代码全部放入唯一的名空间MYAPP中,会大大减少全局变量冲突之可能。
众老牌的JavaScript库都是如此干的:jQuery,YUI,underscore等等。
为解决块级作用域,ES6引入了初的重点字let,用let替代var可以表明一个块级作用域的变量。
ES6标准引入了新的根本字const来定义常量,const与let都怀有块级作用域。

六、时间对象

在JavaScript中,Date对象用来表示日期和日。

假如获取系统即时,用:

var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳

瞩目,当前时间是浏览器从本机操作系统获取之时刻,所以无自然标准,因为用户可以管当下工夫设定也外价值。

比方一旦开创一个点名日期与时间之Date对象,可以为此:

var d = new Date(2015, 5, 19, 20, 15, 30, 123);
d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)

JavaScript的月范围用整数表示是0~11,0代表一月,1代表二月

其次种创建一个点名日期以及岁月之措施是分析一个切ISO 8601格式的字符串:

var d = Date.parse('2015-06-24T19:49:22.875+08:00');
d; // 1435146562875

然而其回到的免是Date对象,而是一个工夫穿。不过有工夫戳就得好易地将她换为一个Date:

var d = new Date(1435146562875);
d; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)

时区

为得以展示调整后底UTC时间:

var d = new Date(1435146562875);
d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关
d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时

那当JavaScript中安进展时区转换为?实际上,只要我们传递的凡一个number类型的年月戳,我们就算甭关心时区转换。任何浏览器还足以管一个时日戳正确转换为当地时间。
时间戳是只什么东西?时间穿是一个自增的整数,它代表于1970年1月1日零时整理的GMT时区开始之那一刻,到现的毫秒数。假设浏览器所在电脑的年华是纯粹的,那么世界上管哪个时区的处理器,它们此刻发生的岁月戳数字还是一律的,所以,时间穿可以确切地表示一个随时,并且与时区无关。所以,我们只是需要传递时间戳,或者将时间穿从数据库里读出来,再给JavaScript自动转换为当地时间虽得了。
倘若赢得当前时穿,可以据此:

if (Date.now) {
    alert(Date.now()); // 老版本IE没有now()方法
} else {
    alert(new Date().getTime());
}

七、面向对象编程

JavaScript的面向对象编程和多数别样语言如Java、C#的面向对象编程都不顶相同。
JavaScript不区分类与实例的定义,而是通过原型(prototype)来实现面向对象编程。
JavaScript的原型链和Java的Class区别就是当,它并未“Class”的概念,所有目标还是实例,所谓继承关系而大凡将一个目标的原型指向任何一个靶而已。

7.1 创建对象

JavaScript对每个创建的目标都见面装一个原型,指为其的原型对象。

当我们为此obj.xxx访问一个目标的性能时,JavaScript引擎先以眼前目标及找该属性,如果没找到,就顶那原型对象及摸,如果还不曾找到,就一直上行至Object.prototype对象,最后,如果还尚未找到,就只能返回undefined。

像,创建一个Array对象:

var arr = [1, 2, 3];
其原型链是:

arr —-> Array.prototype —-> Object.prototype —-> null
Array.prototype定义了indexOf()、shift()等办法,因此你可以于具备的Array对象上直接调用这些艺术。

当我们创建一个函数时:

function foo() {
return 0;
}
函数也是一个目标,它的原型链是:

foo —-> Function.prototype —-> Object.prototype —->
null
由Function.prototype定义了apply()等艺术,因此,所有函数都可调用apply()方法。

颇轻想到,如果原型链很丰富,那么看一个靶的属性就见面以花还多的日子找而更换得更缓慢,因此只要顾不要把本来型链搞得太长。

构造函数

除开直接用{ …
}创建一个对象外,JavaScript还可以用相同种构造函数的措施来创建对象。它的用法是,先定义一个构造函数:

function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
}

以JavaScript中,可以用要字new来调用此函数,并返回一个对象:

var xiaoming = new Student('小明');
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!

瞩目,如果不写new,这就算是一个惯常函数,它返回undefined。但是,如果写了new,它就是变成了一个构造函数,它绑定的this指为新创建的靶子,并默认返回this,也就是说,不欲在终极写return
this;。

初创的xiaoming的原型链是:

xiaoming —-> Student.prototype —-> Object.prototype —->
null
也就是说,xiaoming的原型指向函数Student的原型。如果你以创造了xiaohong、xiaojun,那么这些目标的原型与xiaoming是相同的:

xiaoming ↘
xiaohong -→ Student.prototype —-> Object.prototype —-> null
xiaojun ↗
就此new
Student()创建的靶子还由原型上得到了一个constructor属性,它指向函数Student本身:

xiaoming.constructor === Student.prototype.constructor; // true
Student.prototype.constructor === Student; // true
Object.getPrototypeOf(xiaoming) === Student.prototype; // true
xiaoming instanceof Student; // true

现今咱们就觉着xiaoming、xiaohong这些目标“继承”自Student。

而还有一个稍问题,注意观察:

xiaoming.name; // '小明'
xiaohong.name; // '小红'
xiaoming.hello; // function: Student.hello()
xiaohong.hello; // function: Student.hello()
xiaoming.hello === xiaohong.hello; // false

xiaoming和xiaohong各自的name不同,这是针对性的,否则我们鞭长莫及区分谁是何许人也了。

xiaoming和xiaohong各自的hello是一个函数,但其是有限个不同之函数,虽然函数名称和代码都是同样之!

要我们透过new
Student()创建了广大目标,这些目标的hello函数实际上仅需要联合享同一个函数就足以了,这样好省成千上万内存。

一旦被创建的目标共享一个hello函数,根据目标的特性查找条件,我们要拿hello函数移动到xiaoming、xiaohong这些目标同之原型上便好了,也就算是Student.prototype:

protos2

改代码如下:

function Student(name) {
this.name = name;
}

Student.prototype.hello = function () {
alert(‘Hello, ‘ + this.name + ‘!’);
};

因此new创建基于原型的JavaScript的目标就是这样简单!

忘记写new怎么办

假如一个函数被定义为用于创建对象的构造函数,但是调用时忘记了写new怎么收拾?

当strict模式下,this.name =
name将报错,因为this绑定为undefined,在非strict模式下,this.name =
name不报错,因为this绑定为window,于是无意间创建了全局变量name,并且返回undefined,这个结果再糟糕。

故此,调用构造函数千万不要遗忘写new。为了区别普通函数和构造函数,按照预定,构造函数首字母应当大写,而常见函数首字母应当小写,这样,一些语法检查工具如jslint将得以协助您检测及漏写的new。

最后,还足以编制一个createStudent()函数,在里封装所有的new操作。一个常用之编程模式像这样:

function Student(props) {
    this.name = props.name || '匿名'; // 默认值为'匿名'
    this.grade = props.grade || 1; // 默认值为1
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

function createStudent(props) {
    return new Student(props || {})
}

这createStudent()函数有几乎单伟大的独到之处:一凡是匪需new来调用,二凡参数非常灵活,可以免污染,也可如此传:

var xiaoming = createStudent({
name: ‘小明’
});

xiaoming.grade; // 1
假使创建的靶子来成千上万性能,我们特需要传递需要的少数性能,剩下的性可以用默认值。由于参数是一个Object,我们不管需记忆参数的相继。如果正好从JSON拿到了一个靶,就可一直开立有xiaoming。

7.2 原型继承

于传统的基于Class的言语如Java、C++中,继承的本质是扩张一个就有些Class,并充分成新的Subclass。

鉴于当时类似语言严格区分类与实例,继承实际上是种的壮大。但是,JavaScript由于应用原型继承,我们无能为力直接扩展一个Class,因为从来未存在Class这种类型。

然而办法还是有。我们先行想起Student构造函数:

function Student(props) {
this.name = props.name || ‘Unnamed’;
}

Student.prototype.hello = function () {
alert(‘Hello, ‘ + this.name + ‘!’);
}
以及Student的原型链:

js-proto

而今,我们如果依据Student扩展出PrimaryStudent,可以预先定义有PrimaryStudent:

function PrimaryStudent(props) {
// 调用Student构造函数,绑定this变量:
Student.call(this, props);
this.grade = props.grade || 1;
}
但是,调用了Student构造函数不抵继承了Student,PrimaryStudent创建的靶子的原型是:

new PrimaryStudent() —-> PrimaryStudent.prototype —->
Object.prototype —-> null
要想艺术将原来型链修改为:

new PrimaryStudent() —-> PrimaryStudent.prototype —->
Student.prototype —-> Object.prototype —-> null
如此,原型链对了,继承关系就对了。新的根据PrimaryStudent创建的对象不仅能够调用PrimaryStudent.prototype定义的章程,也得以调用Student.prototype定义之方。

而你想就此最为简单易行粗暴的道这么干:

PrimaryStudent.prototype = Student.prototype;
凡怪的!如果这样的话,PrimaryStudent和Student共享一个原型对象,那还要定义PrimaryStudent干啥?

我们务必依赖一个中档对象来兑现科学的原型链,这个当中对象的原型要依为Student.prototype。为了落实即时或多或少,参考道爷(就是发明JSON的不得了道格拉斯)的代码,中间对象好就此一个空函数F来兑现:

// PrimaryStudent构造函数:
function PrimaryStudent(props) {
Student.call(this, props);
this.grade = props.grade || 1;
}

// 空函数F:
function F() {
}

// 把F的原型指向Student.prototype:
F.prototype = Student.prototype;

//
把PrimaryStudent的原型指向一个初的F对象,F对象的原型正好指向Student.prototype:
PrimaryStudent.prototype = new F();

// 将PrimaryStudent原型的构造函数修复也PrimaryStudent:
PrimaryStudent.prototype.constructor = PrimaryStudent;

// 继续当PrimaryStudent原型(就是new F()对象)上定义方法:
PrimaryStudent.prototype.getGrade = function () {
return this.grade;
};

// 创建xiaoming:
var xiaoming = new PrimaryStudent({
name: ‘小明’,
grade: 2
});
xiaoming.name; // ‘小明’
xiaoming.grade; // 2

// 验证原型:
xiaoming.proto === PrimaryStudent.prototype; // true
xiaoming.proto.proto === Student.prototype; // true

// 验证继承关系:
xiaoming instanceof PrimaryStudent; // true
xiaoming instanceof Student; // true
因此同摆设图来表示初的原型链:

js-proto-extend

顾,函数F仅用于桥接,我们仅仅创建了一个new
F()实例,而且,没有改变旧的Student定义之原型链。

一旦把承这个动作用一个inherits()函数封装起来,还可隐藏F的定义,并简化代码:

function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
夫inherits()函数可以复用:

function Student(props) {
this.name = props.name || ‘Unnamed’;
}

Student.prototype.hello = function () {
alert(‘Hello, ‘ + this.name + ‘!’);
}

function PrimaryStudent(props) {
Student.call(this, props);
this.grade = props.grade || 1;
}

// 实现原型继承链:
inherits(PrimaryStudent, Student);

// 绑定其他办法及PrimaryStudent原型:
PrimaryStudent.prototype.getGrade = function () {
return this.grade;
};
小结

JavaScript的原型继承实现方式就是是:

概念新的构造函数,并在其间用call()调用希望“继承”的构造函数,并绑定this;

依赖中间函数F实现原型链继承,最好通过包的inherits函数完成;

后续于新的构造函数的原型上定义新措施。

7.3 class继承

JavaScript的目标模型是根据原型实现的,特点是简简单单,缺点是亮起来比传统的类-实例模型如果困难,最充分之弱点是继往开来的兑现内需编制大量代码,并且需要是贯彻原型链。

出无出双重简短的写照法?有!

初的重点字class从ES6开端正儿八经给引入到JavaScript中。class的目的就是是为定义类更简约。

咱们先行想起用函数实现Student的法:

function Student(name) {
this.name = name;
}

Student.prototype.hello = function () {
alert(‘Hello, ‘ + this.name + ‘!’);
}
如若因此新的class关键字来修Student,可以如此描绘:

class Student {
constructor(name) {
this.name = name;
}

hello() {
    alert('Hello, ' + this.name + '!');
}

}
于一下即可发现,class的定义包含了构造函数constructor和概念在原型对象上的函数hello()(注意没有function关键字),这样虽避免了Student.prototype.hello
= function () {…}这样分散的代码。

末了,创建一个Student对象代码和前边章节完全一致:

var xiaoming = new Student(‘小明’);
xiaoming.hello();
class继承

因此class定义对象的别样一个宏伟的补益是后续又便宜了。想同一纪念我们从Student派生一个PrimaryStudent需要编制的代码量。现在,原型继承的中游对象,原型对象的构造函数等等都未待考虑了,直接通过extends来实现:

class PrimaryStudent extends Student {
constructor(name, grade) {
super(name); // 记得用super调用父类的构造方法!
this.grade = grade;
}

myGrade() {
    alert('I am at grade ' + this.grade);
}

}
留神PrimaryStudent的定义也是class关键字贯彻之,而extends则表示原型链对象来Student。子类的构造函数可能会见与父类不极端一致,例如,PrimaryStudent需要name和grade两单参数,并且需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。

PrimaryStudent已经自行获得了父类Student的hello方法,我们以于子类中定义了新的myGrade方法。

ES6引入的class和原有的JavaScript原型继承来什么区别也?实际上她从不其它区别,class的企图就是是让JavaScript引擎去实现原需要我们和好修的原型链代码。简而言之,用class的便宜虽大幅度地简化了原型链代码。

君肯定会咨询,class这么好用,能免可知现在即使因故上?

今昔因此还早了碰,因为不是有所的主流浏览器都支持ES6的class。如果一定要是现在即用上,就得一个器把class代码转换为风的prototype代码,可以试试Babel这个家伙。