赞
踩
1)ES6中的默认参数
/* ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法。当传递参数的值为0时,因为0在JavaScript中算是false值,它会直接变成后面硬编码的值而不是0本身 */
function log(x, y) {
y = y || 'World';
console.log(x, y);
}
log('Hello') // Hello World
/* ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 */
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
2)ES6中的模版表达式
//传统的 JavaScript 语言,输出模板通常是这样写的 $('#result').append( 'There are <b>' + basket.count + '</b> ' + 'items in your basket, ' + '<em>' + basket.onSale + '</em> are on sale!' ); //ES6写法: /* 模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量 */ // 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` console.log(`string text line 1 string text line 2`); // 字符串中嵌入变量 let name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` //可以调用函数 const fn=()=>{ return '我是fn函数' } let html = `我是模板字符串${fn()}` console.log(html) // 我是模板字符串 我是fn函数
3)ES6中的拆包表达式/解构赋值
/* ES6之前 */ var data = $('body').data(), // 假设data中有mouse和house的值 house = data.house, mouse = data.mouse /* ES6 */ var { house, mouse} = $('body').data() // 我们会拿到house和mouse的值的 //ES6交换两个变量的值 let a=5; let b=3; [a,b]=[b,a] let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; // foo = 'aaa' // bar = 'bbb' let { baz : foo } = { baz : 'ddd' }; // foo = 'ddd'
4)ES6中改进的对象表达式
7)块级作用域的let和const
let、const和var的差别
//我们用{}来定义块,但是在ES5中这些花括号起不到任何作用 function calculateTotalAmount (vip) { var amount = 0 if (vip) { var amount = 1 } { // 让块来的更疯狂 var amount = 100 { var amount = 1000 //这里的变量定义并不在return层,但也能改变amount的值 } } return amount } console.log(calculateTotalAmount(true)) //输出1000 console.log(amount) //报错 可见,通过var定义的变量不能跨函数作用域访问到 //改成用let function calculateTotalAmount (vip) { var amount = 0 // 或许应该用let, 但你可以混用 if (vip) { let amount = 1 // 第一个数量为 0 } { // 更多的块 let amount = 100 // 第一个数量为 0 { let amount = 1000 // 第一个数量为 0 } } return amount } console.log(calculateTotalAmount(true)) //输出0
var a = [];
//变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量
/*
那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
*/
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
//如果for里使用var定义,则a[6]输出为10
声明提升
函数内部会在开始前先定义需要使用的值,函数定义比变量早
注意:这里指声明提升,是函数里有声明到变量或者函数才会这样,如果函数内部没有声明对应的变量就会往外层找
//内部没有声明变量,往外层找变量值 var a = 10; function test() { console.log("22", a);//10 } test(); console.log("11", a);//10 //内部声明了变量 var a = 10; function test() { console.log("22", a); //undefined var a = 20; console.log("33", a); //20 } test(); console.log("11", a); //10
var flag = true;
if (flag) {
var a = "123";
}
function fn() {
//在这个'b'前面没有var, 会往父层作用域找,一直往上找
//找不到就报错
//程序执行到这个就报错了,比下面的console.log更早
b = 20;
}
fn();
console.log(a);
//b这个变量在全局/局部都没有声明,所以console会报错
console.log(b);
Module 的语法
JS ES6中export和import详解
概述
1)历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。
2)在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。
3)ES6 模块的设计思想是尽量的静态化,使得编译时
就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时
确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。而ES6 模块不是对象。
CommonJS只有运行时才能得到这个对象,从而获取到对象里的属性
4)ES6 模块还有以下好处:
严格模式(严格模式是 ES5 引入的,不属于 ES6)
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
严格模式主要有以下限制。
ES6的模块化无法在Node.js中执行,需要用Babel编辑成ES5后再执行
Export:(变量/函数/class)
// 写法一 export var m = 1; // 写法二 var m = 1; export {m}; // 写法三 var n = 1; export {n as m}; // 报错 export 1; // 报错 var m = 1; export m; // 报错 function f() {} export f; // 正确 export function f() {}; // 正确 function f() {} export {f};
位置:export模块可以位于模块中的任何位置,但是必须是在模块顶层,如果在其他作用域内,会报错。
function foo() {
export default 'bar' // SyntaxError
}
foo()
//写法1 import { firstName, lastName, year } from './profile.js'; function setName(element) { element.textContent = firstName + ' ' + lastName; } //import命令输入的变量都是只读的,因为它的本质是输入接口。 import {a} from './xxx.js' a = {}; // Syntax Error : 'a' is read-only; //但是,如果a是一个对象,改写a的属性是允许的 import {a} from './xxx.js' a.foo = 'hello'; // 合法操作 //写法2:别名 import { lastName as surname } from './profile.js'; //写法3:import语句会执行所加载的模块 //如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次。 import 'lodash'; import 'lodash'; import { foo } from 'my_module'; import { bar } from 'my_module'; // 等同于 import { foo, bar } from 'my_module';
1)注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。
上面的代码不会报错,因为import的执行早于foo的调用
。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。
foo();
import { foo } from 'my_module';
2)由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。
// 报错
import { 'f' + 'oo' } from 'my_module';
// 报错
let module = 'my_module';
import { foo } from module;
// 报错
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
上面三种写法都会报错,因为它们用到了表达式、变量和if结构。在静态分析阶段,这些语法都是没法得到值的。
import * as circle from './circle';
2)注意,模块整体加载所在的那个对象(上例是circle),应该是可以静态分析的,所以不允许运行时改变
。
import * as circle from './circle';
// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {};
export default
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
export default 和 export 区别:
模块的继承:模块之间也可以继承
export * from 'circle'; //export *,表示再输出circle模块的所有属性和方法
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
//只输出circle模块的area方法,且将其改名为circleArea。
export { area as circleArea } from 'circle';
import和export命令只能在模块的顶层,不能在代码块之中。否则会语法报错
这样的设计,可以提高编译器效率,但是没有办法实现运行时加载
。
因为require是运行时加载,所以import命令没有办法代替require的动态加载功能。
所以引入了import()函数。完成动态加载
。
import()返回一个Promise对象, import()也可以用在 async 函数之中。
const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
1)import()函数适用场合
//1.按需加载: button.addEventListener('click', event => { import('./dialogBox.js') .then(dialogBox => { dialogBox.open(); }) .catch(error => { /* Error handling */ }) }); //2.条件加载 if (condition) { import('moduleA').then(...); } else { import('moduleB').then(...); } //3.动态的模块路径 //import()允许模块路径动态生成。下面代码中,根据函数f的返回结果,加载不同的模块。 import(f()) .then(...);
//JavaScript 模块的循环加载
// a.js
var b = require('b');
// b.js
var a = require('a');
什么要使用模块化?都有哪几种方式可以实现模块化,各有什么特点
ES6 模块与 CommonJS 模块有三个重大差异。
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
9)(…)展开运算符
function test(...params){
console.log(params)//[1, 2, 3, 4]
}
test(1,2,3,4)
let [arg1,arg2,...arg3] = [1, 2, 3, 4];
const [arg, ...arg1, arg2] = ["a", "b", "c", "d"]; //报错
//注意:结构赋值中展开运算符只能用在最后。
10)字符串新增方法
确定一个字符串是否包含在另一个字符串中
es5:indexOf
es6:ncludes()
repeat方法返回一个新字符串,表示将原字符串重复n次。
字符串补全长度的功能
padStart()用于头部补全
padEnd()用于尾部补全
padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
消除字符串头部的空格、消除尾部的空格
es5 :trim()
es6:trimStart(),trimEnd()
11)set数据结构,set没有重复的值
let arr = [1,2,3,4,6,3,3,1,3,4];
let removeRepeat = [...new Set(arr)];
console.log(removeRepeat); //[1, 2, 3, 4, 6]
JS数据类型
8种。Number、String、Boolean、Null、undefined、object、symbol、bigInt。
null表示空对象
undefined表示已在作用域中声明但未赋值的变量
基本类型
String、Number、boolean、null、undefined。
引用类型:
object:包含 function、Array、Date。RegExp,Error
基本数据类型的数据直接存储在栈中;而引用数据类型的数据存储在堆中,每个对象在堆中有一个引用地址。引用类型在栈中会保存他的引用地址,以便快速查找到堆内存中的对象。
顺便提一句,栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用内存的消耗
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。