新手小白ES6常用知识点总结

let 和 const

1、使用let声明变量

在JS中,JS代码是交给JS解析线程来处理的,在开始执行前会有一个预编译的过程。var声明的变量会提升。例如:

console.log(a); // undefined
var a = 110;
console.log(a); // 110
复制代码

用var声明的变量除了在函数中是局部变量外,其余都是全局变量,并且可以重复声明。

ES6在之前的基础上,新增了let命令来声明变量。它的用法类似于var,但是声明的变量只在块级作用域内有效,即{}。 并且为了纠正var命令会发生的“变量提升”现象,改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

{
    console.log(a); // not defined
    let a = 110;
    console.log(a); // 110 
}
console.log(a); // not defined
复制代码

除此,let还不允许在相同作用域内,重复声明一个变量。可以说是大大的优化了var的语法漏洞。

补充:因为let的块级作用域,十分适合做for循环的计数器。例如:

for(let i=0;i<10;i++){
    console.log(i);
}
复制代码

上面的代码如果使用var,最后输出的是10。 然而let有着块级作用域,当前的i只在本轮循环中有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是0~10。


2、使用const声明常量

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const a = 11;
a = 22; // 再次赋值就会报错
复制代码

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const与let命令有很多相同之处:用const声明的变量也是不提升的,不可重复声明,且只在声明所在的块级作用域内有效。

还有,如果const声明的是一个对象,对象里面所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的内存地址不能改变,而变量成员是可以修改的。

const a = {name:"wangcai"};
a.name = "xiaoqiang"; // 没问题
a = {name:"xiaoqiang"}; // 报错
复制代码

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于基本数据类型,值就保存在变量指向的那个内存地址,因此等同于常量。但对于引用数据类型,变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。




函数

1、箭头函数

目前我们所知道的创建函数有两种方式:

function f(){} // 函数声明
var f = function(){} // 函数表达式
复制代码

在ES6中,又为我们增加了一个创建函数的快捷写法——箭头函数,不需要function关键字。

var f = () => {} 
复制代码

注意细节:

  • 当函数有且仅有一个参数时,可以省略掉小括号。

  • 当函数返回有且仅有一个表达式时,可以省略{}和return;

    // 例如:
    var f = x => x*x;
    
    // 等价于:
    var f = function(x){
        return x*x;
    }
    复制代码

2、函数默认参数

在ES6中,JS的形参可以有默认值,以便在没有实参被传递进去时使用。

function f(x,y=100){
    return x+y;
}
console.log(f(1));
复制代码

通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。参数变量是默认声明的,所以不能用let或const再次声明。否则会报错。


3、函数的length属性

指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。

(function(a){}).length; // 1
(function(a=5){}).length; // 0
(function(a,b,c=5){}).length; // 2
复制代码

这是因为length属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。

但是,如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。

(function(a=5,b,c){}).length; // 0
(function(a,b=5,c){}).length; // 1
(function(a,b,c=5){}).length; // 2
复制代码




字符串扩展

1、模板字符串

传统的JavaScript语言,输出模板通常是这样写的:

var name = "hello";
var age = 18;
console.log("我叫"+name+",今年"+age+"岁了");
复制代码

上面这种写法相当繁琐,所以在ES6中,引入了模板字符串``解决这个问题。

var name = "hello";
var age = 18;
console.log(`我叫${name},今年${age}岁了`);
复制代码

2、trim()

trim方法用于去除字符串空格。

  • trim():去掉左右空格;
  • trimLeft():去掉左空格;
  • trimRight():去掉右空格。
var str = " a b ab ";
console.log(str.trim()); // "a b ab"
console.log(str.trimLeft()); // "a b ab "
console.log(str.trimRight()); // " a b ab"
复制代码

3、includes(), startsWith(), endsWith()

传统上,JS中只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。除此之外,ES6又提供了三种新方法:

  • includes():表示是否找到了参数字符串。
  • startsWith():表示参数字符串是否在原字符串的头部。
  • endsWith():表示参数字符串是否在原字符串的尾部。
var str = "abc def";
console.log(s.startsWith("abc")); // true
console.log(s.endsWith(" def")); // true
console.log(s.includes("cd")); // false
复制代码

4、repeat()

repeat方法返回一个新字符串,表示将原字符串重复n次。

"123".repeat(3); // 123123123
"123".repeat(2.9); // 123123
"123".repeat(-1); // 报错
"123".repeat(0); // ""
"123".repeat("3"); // 123123123
复制代码
  • 参数如果是小数,会被取整。
  • 如果参数是负数,会报错。
  • 如果没有参数或参数为0,则结果为""。
  • 如果参数是字符串,则会先转换成数字。

5、padStart(),padEnd()

ES7中引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

padStart和padEnd中有两个参数,第一个参数用来指定字符串的长度,第二个参数是用来补全的字符串。

abc.padStart(5,"*"); // "**abc"
abc.padEnd(5,"*"); // "abc**"
复制代码

如果用来补全的字符串与原字符串,两者的长度之和超过了指定的长度,则会截去超出位数的补全字符串。

abc.padStart(5,"123"); // "12abc"
abc.padEnd(5,"123"); // "abc12"
复制代码

如果原字符串的长度,等于或大于指定的长度,则返回原字符串。

abc.padStart(2,"123"); // "abc"
abc.padEnd(2,"123"); // "abc"
复制代码

如果省略第二个参数,默认使用空格补全长度。

abc.padStart(10); // "       abc"
abc.padEnd(10); // "abc       "
复制代码




数组扩展

在ES6中,Array对象增加了一些新的静态方法,Array原型上也增加了一些新方法。

1、Array.from()

Array.from()是Array构造器的静态方法。作用是:将伪数组对象和可遍历的对象转化成真正的数组。

伪数组对象包括:函数中的arguments、由document.getElementsByTagName()返回的数组对象、新增加的Map和Set数据结构。

let lis = document.getElementsByTagName("li");
console.log(Array.isArray(lis)); // false
console.log(Array.isArray(Array.from(lis))); // true
复制代码

如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组。

console.log(Array.from([1,2,3])); // [1,2,3]
复制代码

2、Array.of()

Array.of()方法用于将一组值转换为数组。可以理解为用来创建数组。

主要目的是弥补构造器Array()的不足:因为参数个数的不同,会导致Array()的行为有差异。

console.log(Array()); // []
console.log(Array(3)); // [<3 empty items>]
console.log(Array("3")); // ['3']
console.log(Array(1,2,3)); // [1,2,3]

console.log(Array.of()); // []
console.log(Array.of(3)); // [3]
console.log(Array.of("3")); // ['3']
console.log(Array.of(1,2,3)); // [1,2,3]
复制代码

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。


3、find() 和 findIndex()

find:用于找出第一个符合条件的数组元素。找不到则是undefined。注意,它是不会返回多个,只找一个,找到了就返回。如果你要把所有的满足条件的数组元素素都找出来,你应该用filter()

findIndex:返回第一个符合条件的数组元素的索引。找不到则是-1;

let arr = [
    {name:"zs1",score:85},
    {name:"zs2",score:91},
    {name:"zs3",score:88},
    {name:"zs4",score:74},
    {name:"zs5",score:59},
]
let rs = arr.find(item=>item.score>85)
console.log(rs); // { name: 'zs2', score: 91 }
let f = arr.findIndex(item=>item.score>85)
console.log(f); // 1
复制代码

4、includes()

includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。

let arr = [1,2,3]
console.log(arr.includes(1)); // true
console.log(arr.includes("a")); // false
复制代码

没有该方法之前,我们通常使用数组的indexOf方法,indexOf()也可以做类似的工作。返回值是:0或-1

let arr = [1,2,3]
console.log(arr.indexOf(1)); // 0
console.log(arr.indexOf("a")); // -1
复制代码

但是,因为indexOf它内部使用严格相等运算符(===)进行判断,对NaN的判断是错误的,而includes没有这个问题。

console.log([NaN,1,2,3].indexOf(NaN)); // -1
console.log([NaN,1,2,3].includes(NaN)); // true
复制代码

5、fill()

作用:给数组填充指定值。fill方法用于空数组的初始化非常方便。但是已有数据会被覆盖。

let arr = new Array(5);
console.log(arr.fill("*")); // ['*','*','*','*','*']
console.log([1,2,3].fill("*")); // ['*','*','*']
复制代码

fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置(表示下标,包括起点,不包括终点)。

let arr = new Array(5);
console.log(arr.fill("*",0,2)); // ['*','*',<3 empty items>]
console.log([1,2,3].fill("*",1,2)); // [1,'*',3]
复制代码

6、数组的扩展运算符

扩展运算符是三个点(...),用于在特定地方扩展元素,写法简便快捷,用法也十分给力。

(1)复制数组

let arr = [1,2,3];
let arr1 = [...arr]
console.log(arr1); // [1,2,3]
arr1[0] = 66;
console.log(arr); // [1,2,3]
console.log(arr1); // [66,2,3]
复制代码

上面代码中,用...很简单的复制了一个新数组,且若修改arr1中的值不会对arr产生任何影响产生影响。

(2)合并数组

扩展运算符不仅可以合并数组,还可以在一个数组中扩展另一个数组的元素。

let arr = [1,2,3];
let arr1 = [4,5,6]
let arr2 = [...arr,...arr1,7,8,9]
console.log(arr2); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
复制代码

(3)字符串转成数组

let str = "hello";
let arr = [...str]
console.log(arr); // [ 'h', 'e', 'l', 'l', 'o' ]
复制代码

(4)伪数组转成数组

let lis = document.getElementsByTagName("li");
console.log(Array.isArray(lis)); // false
console.log(Array.isArray([...lis])); // true
复制代码

目前把一个伪数组转成数组有如下几种方式:

  • Array.prototype.slice.call();
  • Array.from();
  • [...伪数组对象]

7、数组的解构赋值

ES6允许按照一定模式,从数组中提取值,对变量进行赋值,这被称为解构(Destructuring)。

以前,为变量赋值,只能直接指定值。

let arr = [1,2,3]
let a = arr[0];
let b = arr[1];
let c = arr[2];
复制代码

ES6可以用解构模式,从数组中提取值,按照对应位置,直接对变量进行赋值。

let [a, b, c] = [1, 2, 3];
复制代码

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

注意细节:

(1)左右结构不一样

let [a,b,c,d] = [1,2,3]
console.log(a); 
console.log(b); 
console.log(c); 
console.log(d); // undefined
复制代码

(2)跳过部分

let [a,,c] = [1,2,3]
console.log(a); // 1
console.log(c); // 3
复制代码

(3)默认值

let [a=11,b=22,c,d=666] = [0]
console.log(a); // 0
console.log(b); // 22
console.log(c); // undefined
console.log(d); // 666
复制代码

(4)嵌套

let [a,b,c,[d]] = [1,2,[3],[4]]
console.log(a); // 1
console.log(b); // 2
console.log(c); // [3]
console.log(d); // 4
复制代码




对象扩展

1、对象的简写

(1)属性的简写

属性名是可以简写的,但是有前提条件:属性的值是一个变量;变量名称和键名是一致的。

var name = "wangcai";
var age = 20;
var obj = {
    //name:name,age:age
    name,age
};
复制代码

(2)方法的简写

除了属性,方法也可以简写,可以省略掉:和function。

var obj = {
    // hello:function(){console.log("hello...")}
    hello(){console.log("hello...")}
};
复制代码

2、属性名表达式

JS定义对象的属性,有两种方法。除了我们最常用的.语法,还有一个[]语法,使用如下:

  • 对象名.[“属性名”]
  • 对象名.[变量]
  • 对象名.[常量]
  • 对象名.[表达式]
var obj = {
    name:"wangcai",
    3:false,
};
var m = "name";
console.log(obj["name"]);
console.log(obj[m]); // wangcai
console.log(obj.m); // undefined
console.log(obj[3]);
console.log(obj["n"+"a"+"m"+"e"]);
复制代码

如果属性是一个变量,那么只能通过[]语法。所以说[]语法更加灵活,能力比.语法更强大。


3、Object.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

var obj1 = {a:0};
var obj2 = {a:1};
var obj3 = {a:11,b:22};
console.log(Object.assign(obj1,obj2,obj3)) // { a: 11, b: 22 }
复制代码

Object.assign也可以用来处理数组,但是会把数组视为对象。

Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3]
复制代码

注意细节:

  • 第一个参数是目标对象,assign这个方法把其它的参数中的属性全部加在第一个参数身上;
  • 第一个参数在属性复制过程中会被修改,后面的会覆盖前面的属性;
  • assign这个方法的返回值就是第一个参数的引用,也就是返回了第一个参数;
  • assign这个方法会把原型上面的属性也拷贝过来;
  • assign不能拷贝继承过来的属性;
  • assign也不能拷贝不可枚举的属性;
  • assign是浅拷贝(仅拷贝内存地址)。

4、对象扩展运算符

对象中的扩展运算符类似于数组中的扩展运算符,作用是取出参数对象的所有可遍历属性,拷贝到当前对象中。一般用于复制对象,合并对象等。

不同的是,对象是{},数组是[],在打印输出时若...被()包起来,[]可以省略不写。

let obj = {a:1,b:2};
let arr = [1,2,3];
console.log({...obj}); // { a: 1, b: 2 }
console.log(...arr); // 1 2 3

let obj1 = {
    a:1,b:2,c:3
};
let obj2 = {
    d:4,e:5
}
let rs = {...obj1,...obj2}
console.log(rs); // { a: 1, b: 2, c: 3, d: 4, e: 5 }
复制代码

5、属性相关的方法

(1)Object.getOwnProertyDescriptor()

获取一个对象中某个属性的详细信息。

var a = 110;
console.log(Object.getOwnPropertyDescriptor(window,"a"));
复制代码

(2)Object.defineProperty()

精细化设置一个对象的属性。属性的四个特征:

  • configurable:是否可以删除。默认为true,可以删除;
  • writable:是否可以修改。默认为ture, 可以修改;
  • enumerable:是否可以枚举。默认为ture, 可以枚举;
  • value:值。默认值为undefined。

格式:Object.defineProperty(对象名,“属性名”,{上面的四个特征});

var obj = {};
Object.defineProperty(obj,"name",{
    configurable:false,
    writable:false,
    enumerable:false,
    value:"wangcai"
})
复制代码

(3)Object.defineProperties()

精细化设置多个对象的属性。

var obj = {};
Object.defineProperty(obj,{
    "name":{
        configurable:false,
        writable:false,
        enumerable:false,
        value:"wangcai"
    },
    "age":{
        configurable:false,
        writable:false,
        enumerable:false,
        value:"66"
    }  
})
console.log(obj.name,obj.age); // wangcai 66
复制代码

(4)Object.getOwnPropertyNames()

获取自身的属性,以数组的格式返回的。

var obj = {
    name:"wangcai",
    age:20
}
console.log(Object.getOwnPropertyNames(obj)); // ['name', 'age']
复制代码

(5)Object.keys()

用来获取对象自身可枚举的属性键,以数组的形式返回。

var obj = {
    name: "wangcai",
    age: 66
};
Object.defineProperty(obj, "name", {
    enumerable: false,
});
console.log(Object.keys(obj)); // ['age']
复制代码

目前对于对象的遍历有三种方式:

  • for in:会输出自身以及原型链上可枚举的属性;
  • Object.getOwnPropertyNames():用来获取对象自身的全部属性名;
  • Object.keys():用来获取对象自身可枚举的属性键。

(6)Object.values()

用来获取对象自身可枚举的属性值,以数组的形式返回。

var obj = {
    name: "wangcai",
    age: 66
};
Object.defineProperty(obj, "name", {
    enumerable: false,
});
console.log(Object.values(obj)); // [66]
复制代码

6、继承相关的方法

(1)Object.create()

使用Object.create比较适合对字面量对象的继承。

function NBA(name,age,height){
    this.name = name;
    this.age = age;
    this.height = height;
}
NBA.prototype.say = function(){
    console.log(`我是${this.name},今年${this.age},身高是${this.height}cm`);
}
var n1 = new NBA("库里",30,191); 
var n2 = Object.create(n1); 
复制代码

(2)Object.setPrototypeOf() 和 Object.getPrototypeOf()

Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。

// 格式
Object.setPrototypeOf(object, prototype)
复制代码

Object.setPrototypeOf与Object.setPrototypeOf方法配套,用于获取创建这个对象的那个构造器的prototype属性。

var obj = {
    name: "wangcai",
    age: 66
};
console.log(Object.getPrototypeOf(obj) == Object.prototype); // true
console.log(Object.getPrototypeOf([]) == Array.prototype); // true
复制代码

7、防篡改方法

可以对对象进行保护,分为三个级别:

  • Object.preventExtensions():不允许新增,但是可以修改,也可以删除;

    var obj = {
        name: "wangcai",
        age: 66
    };
    Object.preventExtensions(obj);
    obj.sex = "man";
    console.log(obj); // Object {name: "wangcai", age: 66}
    复制代码
  • Object.seal():不允许新增,也不允许删除,但是可以修改;

    var obj = {
        name: "wangcai",
        age: 66
    };
    Object.seal(obj);
    delete obj.age;
    console.log(obj); // Object {name: "wangcai", age: 66} 
    复制代码
  • Object.freeze():不允许新增,也不允许删除和修改。

    var obj = {
        name: "wangcai",
        age: 66
    };
    Object.freeze(obj);
    obj.age = 88; 
    console.log(obj); // Object {name: "wangcai", age: 66}
    复制代码

也可以使用isExtensible, isSealed, isFrozen来判断当处处理如个保护状态

var obj = {
    name: "wangcai",
    age: 66
};
// Object.isExtensible()表示是否可扩展
console.log(Object.isExtensible(obj)); // true

Object.freeze(obj);
console.log(Object.isExtensible(obj)); // false
console.log(Object.isSealed(obj)); // true
console.log(Object.isFrozen(obj)); // true
复制代码




严格模式

之前学习的JS,语法非常灵活,JS中这个灵活的特性,弊大于先利。后来增加了严格模式。使用严格模式的目的:规范化、提高编译效率。启动严格模式:"use strict"。

严格模式和非严格模式有什么区别:

  • 在严格模式下,不能使用没有var的变量
  • 在严格模式下,不能使用8进制的数字
  • 在严格模式下,不能把函数定义在if语句中
  • 在严格模式下,函数不能有重名的形参
  • 在严格模式下,function中的this就不再是window了
  • 在严格模式下,arguments不再跟踪形参的变化,即不再与形参一一对应了
  • 还可以在函数中启动严格模式
"use strict"
// a = 100;
// var a = 01;
// if(true){
    // function f(a,a){
    //     console.log("f....");
    // }
// }
// f();
function f(a,b){
    "use strict"
    console.log(this); //undefined
    console.log(a,b); //1,2
    console.log(arguments[0],arguments[1]); //1,2
    arguments[0] = 1111;
    arguments[1] = 2222;
    console.log(a,b); // 1,2
    console.log(arguments[0],arguments[1]); // 1111,2222
}
f(1,2);
复制代码




Set 和 Map 结构

1、Set

Set是一种新的数据结构,它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成Set数据结构。生成时会自动去重。

Set的四个操作方法:

  • add(value):添加某个值,返回 Set 结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。
// 里面要放一个数组 []
var s = new Set([1,2,3,1,2,3])
// 可以使用add()添加元素
s.add(4);
s.add(5);
s.add(4);
s.add(5);
s.delete(5); // 删除
console.log(s); // Set(5) {1, 2, 3, 4, 5}
console.log(typeof s); // object
复制代码

Set中可以用forEach和for of遍历,for in不行。

s.forEach(item=>console.log(item)); 
for(var p of s){
    console.log(p);
}
复制代码

Set不是数组,只是一个像对象的伪数组

console.log(Array.isArray(s)); // false
console.log(Array.isArray(Array.from(s))); // true
复制代码

Set的经典应用案例————数组去重:

// 扩展运算符和Set结构相结合,就可以去除数组的重复成员。
var arr = [1,2,3,1,2,3,true,"hello",true]
var arr1 = [...(new Set(arr))]
console.log(arr1); // [1,2,3,true,"hello"]
复制代码

2、Map

JavaScript的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

为了解决这个问题,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的Hash结构实现。如果你需要“键值对”的数据结构,Map比Object更合适。

  • set(key, value):set方法设置键名key对应的键值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。

  • get(key):get方法读取key对应的键值,如果找不到key,返回undefined。

var a = true;
var m = new Map([
    [a,"hello"],
    [1,123],
    [false,{name:"wangcai"}],
    [[1,2,3],a]
]);
console.log(m); // Map {
                //   true => 'hello',
                //   1 => 123,
                //   false => { name: 'wangcai' },
                //   [ 1, 2, 3 ] => true }

// 对于基本数据类型,重复的键会覆盖
m.set(true,"abc");
m.set([1,2,3],1);
console.log(m); // Map {
                //   true => 'abc',
                //   1 => 123,
                //   false => { name: 'wangcai' },
                //   [ 1, 2, 3 ] => true,
                //   [ 1, 2, 3 ] => 1 }

console.log(m.get(1)); // 123
// m.get([1,2,3])获取不到值的原因是:get()要比较栈区中的地址,而不是堆区中的数据
console.log(m.get([1,2,3])); // undefined
复制代码




Class

1、简介

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改写,就是下面这样。

//定义类
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return this.x + this.y ;
  }
}
var point = new Point(2, 3);
复制代码

上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5的构造器Point,对应ES6的Point类的构造方法。


2、严格模式

类和模块的内部,默认就是严格模式,所以不需要使用 "use strict" 指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。

考虑到未来所有的代码,其实都是运行在模块之中,所以ES6实际上把整个语言升级到了严格模式。


3、constructor

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

class Point {
}

// 等同于
class Point {
  constructor() {}
}
复制代码

4、Class的静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

class Point {
    static say(){ console.log("hello")}
}
Point.say();
复制代码

5、Class的继承

(1)简介

Class 可以通过extends关键字实现继承,这比ES5的通过原型链实现继承,要清晰和方便很多。

class Point {
}

class ColorPoint extends Point {
}
复制代码

(2)Object.getPrototypeOf()

Object.getPrototypeOf方法可以用来从子类上获取父类。因此,可以使用这个方法判断,一个类是否继承了另一个类。

Object.getPrototypeOf(ColorPoint) === Point // true
复制代码

(3)super关键字

super()代表调用父类的构造函数。ES6要求,子类的构造函数必须执行一次super函数。

class A {}

class B extends A {
  constructor() {
    super();
  }
}
复制代码

super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)。

(4)类的prototype属性和__proto__属性

大多数浏览器的ES5实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。

  • 子类的__proto__属性,表示构造函数的继承,总是指向父类。

  • 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

class A {
}

class B extends A {
}

B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
复制代码




新手小白,刚刚上路,学习总结,请多关照!

转载于:https://juejin.im/post/5b6ed766e51d4517df1550a5

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值