全局中的isNaN,会进行数据类型的转换 先尽可能转为数字 再判定
Number.isNaN, 不会进行数据类型的转换 参数只要不是数字类型 就为false
全局中的isFinite,会进行数据类型的转换 先尽可能转为数字 再判定
Number.isFinite, 不会进行数据类型的转换 参数只要不是数字类型 就为false
先判定是否是数字,如果是,再继续判定是否是整数。 如果不是,直接返回false。
与=== 的区别:
1、Object.is(NaN, NaN); => true NaN === NaN => false
2、Object.is(0, -0); => false 0 === -0 => true
Object.assign(obj); 浅复制
obj: 继承者
除了第一个参数之外,后面还可以放任意个参数。每一个参数都是被继承者。
Object.assign(obj, obj1, obj2, obj3);
修改一个对象(被继承者)的时候,影响到了另外一个对象(继承者) 说明是浅复制
jquery的浅复制: . e x t e n d ( o b j , o b j 1 ) ; 深 复 制 : .extend(obj, obj1); 深复制: .extend(obj,obj1);深复制:.extend(true, obj, obj1);
underscore只有浅复制:继承 .extend(obj, obj1);浅复制:.clone(obj1); 返回值是被复制的新对象
目的:对目标对象保护;外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写
new Proxy(targetObject, handlerObject);
targetObject: 被代理的对象;
handlerObject: 访问方式 其实就是ES5里的get set特性
代理对象自身没有任何属性和方法
var obj = {
name: "赵丽颖",
age: 31,
married: "是"
}
// 当该对象不想被人访问时 可以设置代理
var proxy = new Proxy(obj, {
// get表示当通过proxy对象访问obj的属性时 调用的方法以及返回的内容
get: function(target, propName, proxy) {
// 判定
if(propName === "married") {
return "保密";
}
// 如果不是询问婚姻状况,则如实回答
return target[propName];
},
// set表示当通过proxy对象对obj对象的属性进行修改时 调用的方法以及是否设置
set: function(target, propName, value, proxy) {
// 禁止修改名字和年龄
if (propName === "name" || propName === "age") {
return null;
}
// 其它属性可以设置
target[propName] = value;
}
})
数据类型,代表独一无二的符号
属于基本类型(值类型)由Symbol函数生成,参数没有意义,两个Symbol实例永不相同
let s = Symbol("color");
let s1 = Symbol("color");
console.log(s === s1);// false
如果将Symbol当做对象的key 则该key不可枚举
1、当对象的key与对象的value一致时,可以省略 :value
2、使用[] 来定义对象
3、定义对象的方法的时候,可以取消: function了
//使用[] 来定义对象
var user = "student";
// 定义一个对象
var obj = {
[user + "name"]: "你好"
}
console.log(obj)// { studentname: "你好"}
// 定义对象的方法的时候,可以取消: function了
var obj = { intro: function() {} }
//可修改为:
var obj1 = { intro() {} }
var Tom = {
username: "张三",
age: 12,
gender: "男",
married: false
}
var {username, age, gender, married} = Tom;
console.log(username, age, gender, married) //Tom 12 男 false
var arr = [1, 2, 3, 4, 5, 6];
var [a, b, c, d] = arr;
console.log(a, b, c, d) // 1 2 3 4
() => {}
var fun = () => {
console.log(123)
}
fun();
// () 表示参数列表 => 箭头 {} 表示函数体
特点:
1、不能作为构造函数使用
2、this指向不会变化,为window,具体指向由作用域定义的环境所决定
3、省略写法:
只有一个形参,可省略() let fun = arg => { console.log(arg);}
只有一条语句并且是返回语句时 可以省略 {} 和 return; let fun1 = (arg) => arg * arg;
4、箭头函数中没有arguments
1、箭头函数中arguments 补救措施: … 语法
2、解构数组时使用
3、…语法逆运用实现copyWithin方法
var fun = (...args) => {
console.log(args);
}
fun(1, 2, 3) // [1, 2, 3]
// 实现copyWithin方法
Array.prototype.copyWithin = function(pos, start, end) {
var length = this.length; // 保存原长度
var newArr = this.slice(start, end); // 截取
this.splice(pos, newArr.length, ...newArr);
this.length = length; // 恢复原长度
}
var arr = [1, 2, 3, 4, 5, 6, 7];
arr.copyWithin(3, -2) // => [1, 2, 3, 5, 6, 6, 7];
var iterator = arr.keys();
console.log(iterator.next()); // 得到的是一个对象 对象中有value 表示得到的值 对象中有done 表示是否可以继续迭代
该方法不可逆,当next迭代完毕之后,调用next方法的iterator就没用了。如果想要再次迭代,请重新调用keys、values、entries方法。
for 循环 用于循环数组
for ……in 循环 用于循环对象
for……of循环用于循环迭代器
var iterator = arr.values();
for(var i of iterator) {
// i 是 iterator.next() => {value:xxx, done: false} 中的 value值
console.log(i);
}
之前:对象、数组
ES6新增:Set、 WeakSet、 Map、 WeakMap
类似于数组,但是成员的值都是唯一的,没有重复的值。
实现了迭代器接口,可直接使用for…of循环
Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
内部不会发生类型转换
Array.from方法可以将 Set 结构转为数组。
运用一:数组去重
运用二:字符串去重
var string = "abcdefgadf";
var set = new Set(string);
console.log(set) //{"a"、"b"、"c"、"d"、"e"、"f"、"g"}类似数组
console.log([...set].join("")) //"abcdefg" 先通过...语法转为数组
set实例的属性和方法:
1、Set.prototype.constructor:构造函数,默认就是Set函数。
2、Set.prototype.size:返回Set实例的成员总数。
3、操作方法(用于操作数据):
4、遍历方法(用于遍历成员):
Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
for (let x of set) {
console.log(x);
}
// red
// green
// blue
不重复的值的集合。但是,它与 Set 有两个区别。
首先,WeakSet 的成员只能是引用数据类型,而不能是其他类型的值。
里面的对象都是弱引用,也就是说如果其他对象不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存。工作之中慎用
方法:add、delete、has
WeakSet 没有size属性,没有办法遍历它的成员。不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了
本质上是键值对的集合。超对象,普通对象的key必须是字符串或者是Symbol,Map的key可以是任意类型
方法和属性:
size属性、 delete、 has、 clear 、 get (key) 、 set(key,value)
keys 、 values 、 entries 、 forEach()
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(…)
map.set(false, {}); // {false => {…}}
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()] // [1, 2, 3]
[...map.values()] // ['one', 'two', 'three']
[...map.entries()] // [[1,'one'], [2, 'two'], [3, 'three']]
[...map] // [[1,'one'], [2, 'two'], [3, 'three']]
用于生成键值对的集合。弱类型对象,key必须是对象
方法: get、 set、 has、 delete
特点与WeakSet一致,也是无法被垃圾回收机制纳入回收范围
定义: function * fun () {}
组成: 在状态函数内部 可以通过yield关键字定义任务内容。
执行: 状态函数执行完毕之后,得到的是一个迭代器对象。该迭代器对象每一次执行next方法就会执行一次yeild。
可以将多个异步任务,书写成同步方式
发现:next能够得到return的返回内容 而 for……of迭代无法得到return的返回内容
// 定义一个状态函数
function * Generator() {
// yield 表示“产出”的意思 与return相近
yield "起床";
yield "洗刷";
yield "吃饭";
yield "上课";
yield "high";
yield "下课";
yield "放学";
yield "dota";
yield "吃饭";
yield "code";
yield "睡觉";
return "over";
}
// 执行该状态函数 得到一个迭代器对象
var g = Generator(); // 请不要使用new来调用
// 因为g是一个迭代器对象 g.next()返回一个对象 对象有value 有done
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
// console.log(g.next());
解决异步编程
Promise只是将回调函数内的代码抽取出来放在了代码的下方 代码由横向发展变为纵向发展,更贴近“同步”
Promise只是改变了代码的书写方式,至于异步代码的发送方式不会由异步变为同步
new Promise所接收到的函数会立即执行
一共有3个状态:
pending: 执行中
resolved: 成功
rejected: 失败
then方法:是一个Promise实例的方法,用于接受事件函数。第一个参数是成功时的执行函数,第二个参数是失败时的执行函数。该方法可以多次调用。
允许你在事件执行完毕之后再绑定代码。依旧有效
只可以传递一个参数。resolve方法只能填写一个实参
var p = new Promise(function(resolve, reject) {
// 在这个函数中发送ajax 就是Promise的作用范围 我们可以通过p对象监听这个异步请求的状态
$.ajax({
url: "/data/0.json",
type: "get",
dataType: "json",
success: function(data) {
// 原来我们是将后续代码写在这里面
// 属于回调函数的写法
// 现在我们不将具体的代码写在这里 而是只在这里判定请求是否成功
if(!data.error) {
// 成功
resolve();
} else {
// 失败
reject();
}
}
})
});
// 请求成功与失败的代码在p.then里
p.then(function() {
console.log("成功")
}, function() {
console.log("失败")
})
当从第一个函数处理完毕之后,执行第二个函数时,如果需要传递参数,就需要在第一个函数中 使用return进行传参
p.then(() => {
return 1;
})
.then((data) => {
console.log(data); // 1
})
如果在一个Promise的成功函数中返回了另外一个Promise,则新的then监听的是新Promise
可以处理一个ajax发送完毕之后,发送另外一个ajax
Promise构造函数有一个静态方法all 它接受一个数组数组中的每一项是Promise实例,可以同时监听多个异步行为了
function sendAJAX() {
return new Promise((resolve, reject) => {
$.ajax({
url: "/data/1.json",
success: function(data) {
console.log(1);
resolve("第一个");
}
})
})
}
// 发送另一个ajax
function sendAJAX1() {
return new Promise((resolve, reject) => {
$.ajax({
url: "/data/2.json",
success: function(data) {
console.log(2);
resolve("第二个");
}
})
})
}
// 要求:在两个ajax都执行完毕之后 输出成功
// Promise构造函数有一个静态方法all 它接受一个数组数组中的每一项是Promise实例
// 返回的是一个新的Promise实例
var p_all = Promise.all([ sendAJAX1(),sendAJAX()]);
//这里传参的数组顺序,决定了下面data数组中的顺序
// p_all 是一个新的Promise实例 它可以有then方法
// 这个then方法监听的就是两个Promise实例
p_all.then((data) => {
console.log(data);
console.log("成功") // 第一个函数表示当两个Promise实例都为resolved的时候执行的函数
}, () => {
console.log("失败") // 第二个函数表示当两个Promise实例有任何一个变为reject的时候执行的函数
})
// 传递参数:
// 同时发送的ajax,如果在最后执行的时候需要数据。则需要传递参数。
// then方法的函数形参中的数据类型是数组,该数组的长度与Promise.all监听了几个Promise实例有关。
当连续多个Promise实例调用时,每一次都需要在then中准备两个函数。于是,为了简化书写,Promise提供了catch方法,用于捕获异常和rejected函数
// 先后执行这两个ajax
var p = sendAJAX();
// 监听成功或者失败事件
p.then(() => {
return sendAJAX1();
})
.then(() => {
})
// 捕捉 当以上的Promise实例中任何一个阶段出现了错误或者rejected了将会执行catch中的函数
.catch((data) => {
console.log(data);
})
在ES6之前,script标签的type属性只有一个text/javascript
ES6中,新增了一个属性值选项 module
模块内部的东西是天生无法向外部暴露的。
如果想要引入一个模块,则必须在服务器环境下引入。
<script type="module">script>
<script type="module" src="./js/a.js">script> //必须在服务器环境下引入
使用import关键字
第一种 :import a from “./module/a.js”; 此种方式要求被引入的模块文件中必须有default的值
第二种:import {a} from “./module/a.js”; 此种方式不要求被引入的模块文件中有default值
第三种 :import * as obj from “./module/a.js”;
就是一个普通js文件,export 是关键字,表示“导出”
定义类: class className { }
class Student {
// 构造函数
constructor(name, age, sex) {
//定义实例属性
this.name = name;
this.age = age;
this.sex = sex;
}
// 定义普通方法定义在这里
sayHello() {
// 这里的this是实例
console.log("大家好, 我的名字是" + this.name + "我的年龄是" + this.age + "我是一个" + this.sex + "孩子")
}
// 定义静态方法 也是在这里
static hello () {
console.log("hello")
}
}
// 添加静态属性
// Student.xxx = "xxx";
// 实例化该类
let student = new Student("小明", 12, "男");
语法: class xxx extends XXX {}
super是一个函数,表示调用父类的构造函数 等价于我们之前的构造函数式继承
继承的内容有: 普通属性、 普通方法、 静态方法
// 定义父类
class People {
// 构造函数定义属性
constructor(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 普通方法————给实例调用的
sayHello() {
console.log("Hello, my name is " + this.name);
}
// 静态方法————给类调用的
static hello() {
console.log("hello")
}
}
// 定义子类
class Student extends People {
// 构造函数定义属性
constructor(name, age, sex, grade) {
// 前三个属性可以继承 最后一个不可以
super(name, age, sex);
// 赋值自己的属性
this.grade = grade;
}
}
// 实例化一个父类
let p = new People("张三", 12, "男");
// 调用方法
p.sayHello(); // Hello, my name is 张三
// 实例化一个子类
let s = new Student("小明", 13, "男", 6);
// 调用方法
s.sayHello(); // Hello, my name is 小明
People.hello(); // hello