这里
怎么看都是个坑
4–class
突然看到了class
//4-1
class Bar {
doStuff() {
console.log('stuff');
}
}
var b = new Bar();
b.doStuff() // "stuff"
和Java挺像的用法。这块代码可以很好的展示如何使用Js的class。
//4-2
class Bar {
doStuff() {
console.log('stuff');
}
doBar(){
console.log('bar');
}
constructor(){
}
}
//相当于
Bar.prototype = {
doStuff(){},
doBar(){},
constructor(){},
}
let b = new Bar();
b.constructor === Bar.prototype.constructor
//这里b是Bar的实例
//而类的新方法,可以直接加在prototype上
//这里通过Object.assign方法可以一次性向Bar类加多个方法
Object.assign(Bar.prototype, {
toString(){},
toValue(){}
});
之前不太能看懂js的原型prototype是什么,现在大概是可以理解一点儿。
类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
参考链接两个代码最开始没有看明白,因为里面有两个方法Object.keys()方法和Object.getOwnPropertyNames()从没有用过。
这里需要先了解一下,那么
这个链接里有一个代码非常显而易见的可以理解Object.keys()方法和Object.getOwnPropertyNames()是干嘛用的
代码如下
//4-3
//这是一个拿到不可枚举的对象的方法
var target = myObject;//target是一个Object
var enum_and_nonenum = Object.getOwnPropertyNames(target);//这里用Object.getOwnPropertyNames()方法来拿到存放可枚举和不可枚举的全部对象的数组
var enum_only = Object.keys(target);//这里用Object.keys()方法来拿到可枚举的对象的数组
var nonenum_only = enum_and_nonenum.filter(function(key) {//这里使用数组Array的方法Array.prototype.filter(callback[, thisArg]);
var indexInEnum = enum_only.indexOf(key);//用indexOf判断这个key是否被可枚举对象的数组包含
if (indexInEnum == -1) {
return true;
} else {
return false;
}
});
console.log(nonenum_only);
辣么,既然明白了keys和getOwnPropertyNames这两个方法分别是拿某个类里可枚举的对象和全部对象,在来看参考链接里的两个代码,如下
//4-4
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
//这是ES6的写法
//4-5
var Point = function (x, y) {
// ...
};
Point.prototype.toString = function() {
// ...
};
Object.keys(Point.prototype)
// ["toString"]
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
//这是ES5的写法
这4-4和4-5两个代码的不同之处,首先是对类Point的声明,第一个采用的是ES6的写法,第二个是ES5的写法;两个代码块在输出Object.getOwnPropertyNames(Point.prototype)
的结果都是一样的,在Object.keys(Point.prototype)
却不一样。
由此可见
–ES5和ES6对对象原型上的对象是否可枚举的判断行为是不一致的。
类的默认方法contructor是默认存在的。
constructor
方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。
//4-6
class Point {
}
// 等同于
class Point {
constructor() {}
}
定义了一个空的类Point,JavaScript 引擎会自动为它添加一个空的constructor方法。
对
constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
这个不是很理解。
这句话的例子如下:
//4-7
class Foo {
constructor() {
return Object.create(null);
}
}
console.log(new Foo() instanceof Foo);
// false
instanceof
的详细可以戳这里,或百度。这里的链接提供了一个例子:
//4-8
function Person(){};
var p =new Person();
console.log(p instanceof Person);
//true
恩,好像明白了什么。
让我在找一下,Object.create()
的例子戳这里就够了
Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。
所以4-7这个例子里Foo
类的contructor
方法里其实是用Object.create()
新建了一个对象,所以new Foo()
这个实例对象并不是Foo
类的实例。
类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。
********************6-14新增START********************
看到了 个关于Object.keys()
的东西。
具体链接戳这里。
//4-9 这是源代码
var obj = {'a':'123','b':'345'};
console.log(Object.keys(obj)); //['a','b']
var obj1 = { 100: "a", 2: "b", 7: "c"};
console.log(Object.keys(obj1)); // console: ["2", "7", "100"]
var obj2 = Object.create({}, { getFoo : { value : function () { return this.foo } } });
obj2.foo = 1;
console.log(Object.keys(obj2)); // console: ["foo"]
由这里可以看出,Object.keys()
是获取对象里的键值,并对键值好像是有排序的功能。
那么,
//4-10
var obj = {'b':'345','a':'123','d':'345','c':'345'};
console.log(Object.keys(obj));
//["b", "a", "d", "c"]
var obj1 = { 100: "a",888:"aa",88:"s", 2: "b", 7: "c",1:"ss"};
console.log(Object.keys(obj1));
// ["1", "2", "7", "88", "100", "888"]
对obj和obj1添加了几键值对后,发现,字符串的键值取出来后并没有按照顺序排列;而数字的键值则是按顺序取出来。
*********************6-14新增END*********************
3–数组
ES5把对象变成数组的代码从来没想过,看到这行真的是受益匪浅
//3-1
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
arrayLike里的length必写。
实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。
2–Set
个人以为,ES6提供的最新的这个数据结构Set真的是很牛掰。
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。
//2-1
const items= new Set([1, 2, 3, 4, 4]);
[...set]
//[1,2,3,4]
items.size //4
两行就可以解决你的去重问题。
没错,以前要写5、6行的去重方法,这里两行就可以完全搞定。
想获取set的长度,直接用items.size
如果想向Set的数据结构里添加数据,
//2-2
const items= new Set([1, 2, 3, 4, 4]);
[2, 3, 5, 4, 5, 2, 2].forEach(x => items.add(x));
console.log(items);//Set(5){1,2,3,4,5}
for (let i of items) {
console.log(i);
}
//1 2 3 4 5
1–let
let是用来申明变量的命令,和var一样。
在js里,如果你不声明一个变量,而是直接使用它,
//1-1
a = 0;
var b = 1;
console.log(a+" "+b);//0 1
代码并不会报错,而是自动将a视为已经声明过的。
而,如果在一个片段里不声明而是直接使用a,代码也并不会报错,
//1-2
var b = 1;
if(b > 0){
a = 0;
}
console.log(a+" "+b);//0 1
但是let就不行了。
//1-3
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
如果在一个片段里用let申明a,在片段外去获取a的话,会报错:a未被定义。
有一种Js越来越像Java的感觉。