vscode + live server插件
重点在css, 更重点在js(java script)
不好看,没有人使用。
head: meta元数据, title标签, link 引入css,script引入外部js, <style> 内联样式
body: 浏览器渲染
ul > li
无序
ol>li
有序
table>tr>th*3
tr>td*3
input
textarea
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>欢迎来到mykernel.cn</h1> <form action="" method="POST" enctype="application/x-www-form-urlencoded"> <table border="1" width="50%"> <tr> <td colspan="2"> 注册</td> </tr> <tr> <td> 用户 </td> <td> <!-- <input type="text" name=""> 只提交有name的部分 --> <input type="text" name="username"> </td> </tr> <tr> <td> 密码 </td> <td> <input type="password" name="password"> </td> </tr> <tr> <td> 性别 </td> <td> <!-- <input type="radio" name="gender" id=""> 男 没有value, 点就是on, 不点就是空 --> <input type="radio" name="gender" id="" value="1" checked> 男 <input type="radio" name="gender" id="" value="0"> 女 </td> </tr> <tr> <td> 爱好 </td> <td> <input type="checkbox" name="love" id="" value="1"> music <input type="checkbox" name="love" id="" value="2" checked> movie <input type="checkbox" name="love" id="" value="3"> game </td> </tr> <tr> <td> 其他描述 </td> <td> <textarea name="desc" id="" cols="30" rows="10"></textarea> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="提交"> <input type="reset" value="重置"> </td> </tr> </table> </form> </body> </html>
<form action="" method="POST" enctype="application/x-www-form-urlencoded">
默认GET方法,参数是查询 参数。POST方法,参数就是请求体,不限制大小,更安全;
application/x-www-form-urlencoded 默认
multipart/form-data 上传文件; input multiple
多文件
<form action="" method="POST" enctype="multipart/form-data"> <input type="file" name="test" id="" multiple>
<!-- <input type="text" name=""> 只提交有name的部分 -->
当我们把上面的name取消之后,只有name有值的部分才会提交
<!-- <input type="radio" name="gender" id=""> 男 没有value, 点就是on, 不点就是空 -->
当radio/checkbox没有value时,点了就是on, 不点就是空。所以给value. radio就给0和1
checkbox就给编号
网页是给人看的,而数据库中实际存储的是数字ID。
<input type="radio" name="gender" id="" value="1" checked> 男
默认值带checked
以后的课程不会使用原生的,但最终也是原生的。
以后不使用以上的enctype, 全部使用json.
样式,布局
行内,内联,外链
123<input type="text" style="border: 0;"> <style> input { outline: none; } </style> <link rel="stylesheet" href="css/1.css">
selector { key1: value1; key2: value2; key3: value3; } selector1, selector2 { key1: value1; key2: value2; key3: value3; }
标签,类,id
多级,同级
伪类,伪元类
p {} # <p></p> .test {} # <input type="text" class="test"> #test {} #<input type="text" id="test"> div p # 多级 div > p # 1级 div > p+a # 同级 # 伪类 a:hover a:first-child # 伪元素 a::before a::after # 属性选择器 e[attr] e[attr=value] e[attr=^value] e[attr=$value]
JS标准很多,浏览器支持的不同,需要解决这个问题。框架就可以解决,我们只管使用最新的框架,不用担心浏览器版本不同。
chinese, live server, node exec(f8一键执行)
配置: ctrl + ,
node exec: f8
javascript/** 回车,完成多行注释
// 完成单行注释
代码中也可以注释,一般在代码上下注释
javascript/**
* 推荐
* 声明方式:
* var 支持提升
* let ES6的新语法,解决var的问题;
* const 声明必须赋值
*/
var b // 声明
b = 'abc' // 赋值
console.log(b);
var b = 'cde', c = 2; // 声明并赋值
console.log(b,c);
let d = 125;
console.log(d);
/**
* 不声明赋值
* 隐式定义;不推荐,严格模式下报错
*/
a = 1
console.log(a);
/**
* 声明不赋值 undefined
*/
var e;
let f;
console.log(e,f);
/**
* 不声明,不赋值 ReferenceError: g is not defined
*/
// console.log(g);
/**
* 常量必须声明+赋值
* SyntaxError: Missing initializer in const declaration
*/
// const h
const h = undefined; // 悬空, python None -> js null
console.log(h);
/**
* 先使用,后声明
* 声明提升
* var 支持提升, undefined
* let 不支持提升, ReferenceError: Cannot access 'abc' before initialization
*/
console.log(ab);
var ab;
// console.log(abc);
let abc;
/**
* 变量引用
* `` 可以引用变量,可以多行
*/
const x= 100, y = 200;
console.log(x,y,`${x} ${y}`); // 100 200 100 200
使用var bug多
作用域
javascriptfunction test() {
a = 100 // 未定义 作用域全局,函数外部可访问;严格模式下禁止
var b = 2 // 作用域在函数中
let c = 3
}
test()
console.log(a);
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined
变量
var a = 100; var a = 200; console.log(a); // 正常 let b = 10; let b = 20; // SyntaxError: Identifier 'b' has already been declared console.log(b);
框架中,使用最多let, 其次const。不要使用var, 隐式定义;
标识不修改,直接定义const。
标识需要修改,直接let。
名称 | 描述 |
---|---|
number | 整型,浮点 |
boolean | true, false |
string | 字符串, ' ' 或 " " |
null | python中的None |
undefined | 悬空的,就是声明不赋值 |
symbol | ES6引入 ,常量 |
object类型 | 类似字典; ES3出现 json js object notation |
javascriptlet obj = {
a: 1, // a不加引号,等价 "a", 'a', `a`; 属性为a, 属性值为1。
"b": 'abc', // 右边值字符串必须使用引号; ' ', ` `, " "
c: undefined,
d: null,
e: [1,2,3], // array 数组 --> python的 list
}
console.log(obj.b,obj.c,obj.d,obj.a, obj.e);
判断语言的强弱
javascript/**
* 是否支持隐式类型转换,正常就是弱类型
*/
console.log('a' + 1);
/**
* 类c语言的语法
* a=, a是标识符
*/
console.log(a='a' + 1,a+'2', typeof (a + '2')); //a1 a12 string
javascriptconsole.log('============== string =====================');
console.log(a = 3 + 'a', typeof(a)); // 3a string
console.log(a = null + 'a', typeof(a)); // nulla string
console.log(a = undefined + 'a', typeof(a)); // undefineda string
console.log(a = true + 'a', typeof(a)); // truea string
javascriptconsole.log('============== number =====================');
console.log(a = null + 8, typeof(a)); // null 为 0 8 number
console.log(a = undefined + 8, typeof(a)); // NaN number
console.log(a = true + 8, typeof(a)); // true 为 1 9 number
console.log(a = false + 8, typeof(a)); // false 0 8 number
javascriptconsole.log('============== bool =====================');
console.log(a = null + true, typeof(a)); // 1 number
console.log(a = null + false, typeof(a)); // 0 number
console.log(a = undefined + true, typeof(a)); // NaN number
console.log(a = undefined + false, typeof(a)); // NaN number
console.log(a = true + true, typeof(a)); // 2 number
console.log(a = false + false, typeof(a)); // 0 number
javascript/**
* & 与
* | 或
* ~ 非
*/
console.log(a = null & true, typeof a); // 0 number
console.log(a = undefined & true, typeof a); // 0 number
javascriptconsole.log('========= null =========');
console.log(a = null + undefined, typeof(a)); // NaN number
console.log(a = null - undefined, typeof(a)); // NaN number
console.log(a = null * undefined, typeof(a)); // NaN number
console.log(a = null / undefined, typeof(a)); // NaN number
javascript/**
* && and 与
* || or 或
* ! not 非
*/
console.log(a = null && true, typeof(a)); // null object
console.log(a = "magedu" && true, typeof(a)); // true boolean
console.log(a = 'magedu' && true, typeof(a)); // true boolean
console.log(a = true && "magedu", typeof(a)); // magedu string
console.log(a = true && 'magedu', typeof(a)); // magedu string
console.log(a = "magedu" && false, typeof(a)); // false boolean
console.log(a = 'magedu' && false, typeof(a)); // false boolean
console.log(a = false && "magedu", typeof(a)); // false boolean
console.log(a = false && 'magedu', typeof(a)); // false boolean
console.log(a = true && '' && 'magedu', typeof(a)); // string
// 1 * 0 * 1 = 0
console.log(a = null || true, typeof(a)); // true boolean
console.log(a = ! null, typeof(a)); // true boolean
// [] , {} 在javascript中识别为true
console.log(a = [] && 'abc', typeof(a)); // abc string
console.log(a = {} && 'abc', typeof(a)); // abc string
javascript/**
* 引用 `${variable}` a
* 索引 []
* 切片,没有 slice
* 大写,小写 toUpperCase, toLowerCase
* 组合, contact, +, ``
* 分割 split
* 替换 replace
* 取子串 substring
* 查询字符串位置 index
* 重复字符中 repeat
* 删除两头 trim
*/
const a = 'mykernel'
console.log(`blog.${a}.cn`); // blog.mykernel.cn
console.log(a[2], a.charAt(2));
// console.log(a[2:5]);
console.log(a.slice(2,5)); // ker
console.log(a.slice(2)); // kernel
console.log(a.slice(2,-1)); // kerne
console.log(a.toUpperCase()); // MYKERNEL
console.log(a.toLowerCase()); // mykernel
const b = ('blog.' + a).concat('.cn')
console.log(b); // blog.mykernel.cn
console.log(b.split('.')); // [ 'blog', 'mykernel', 'cn' ]
console.log(b.replace('blog.','liangcheng.')); // liangcheng.mykernel.cn
console.log(b.substring(0)); // blog.mykernel.cn
console.log(b.substring(0,b.length)); // blog.mykernel.cn
console.log(b.indexOf('.')); // 从左到右,搜索第1个.出现的索引位置 4
console.log(b.indexOf('.',5)); // 从左到右,搜索第1个.出现的索引位置 13
console.log('-'.repeat(30)); // ------------------------------
console.log('\r\n\t a b\tc\nde\f\n\r\n\r\t '.trim()); // a b c ...de
javascriptvar biggestNum = Number.MAX_VALUE
var smallestNum = Number.MIN_VALUE
var infiniteNum = Number.POSITIVE_INFINITY // 正无穷
var negInfiniteNum = Number.NEGATIVE_INFINITY // 负无穷
var notANum = Number.NaN // 不是数值
二进制 0b
八进制 0O
十六进制 0x
javascript/**
* 取整
* python: int, floor, ceil, round;
* javascript: parseInt, Math.floor, Math.ceil, Math.round;
*
*/
console.log(parseInt('1'));
console.log(1/2); // 0.5 自然除
console.log(Math.floor(0.5));
/**
* parseInt 正数或负数截取整数部分
* floor 正数或负数向下取整
* ceil 正数或负数向上取整
* round 正数或负数 四舍五入 右侧最近整数
*/
console.log('=--------正数------');
let nums = [0.1,0.5,0.6,2.2,2.5,2.9,3.499999,3.50001]
for (let i = 0; i<nums.length; i++) {
console.log(nums[i],parseInt(nums[i]),`parseInt`);
console.log(nums[i],Math.floor(nums[i]),`Math.floor`);
console.log(nums[i],Math.ceil(nums[i]),`Math.ceil`);
console.log(nums[i],Math.round(nums[i]),`Math.round`);
}
console.log('=--------负数------');
for (let j of nums) {
console.log(-j,parseInt(-j),`parseInt`);
console.log(-j,Math.floor(-j),`Math.floor`);
console.log(-j,Math.ceil(-j),`Math.ceil`);
console.log(-j,Math.round(-j),`Math.round`);
}
Math操作
javascript/**
* Math.PI
* Math.abs
* Math.log2 2为底的对数
* Math.sqrt 开根
* Math.pow 次方
* Math.random 随机在(0,1)之间
*/
console.log(Math.PI); //3.141592653589793
console.log(Math.abs(-1)); // 1
console.log(Math.log2(16)); // 4
console.log(Math.sqrt(2), 2**0.5); // 1.4142135623730951
console.log(Math.pow(2,3), 2**3); // 8
console.log(Math.random() ); // 0.18607565307639917
console.log(Math.random() * 100); // (0-100)
console.log(Math.random() * 97); // (0-97)
console.log(Math.random() * 95 + 5); // (5-100) 同时-5 -> (0-95)
console.log(Math.random() * 92 + 5); // (5-97) 同时-5 -> (0-92)
判断
javascript/**
* 判断NaN
*/
let a = undefined + 1
console.log(a); // NaN
console.log(a == NaN); //false
console.log(Number.isNaN(a)); // true
javascriptconsole.log(1/0); // Infinity 正无穷, 特殊的数值
console.log(-1/0); // -Infinity 负无穷, 特殊的数值
自增运算
javascript/**
* 自增: C/C++ 内存中直接增,效率更高;虚拟机语言也类似原则; i++ , ++i
* java当中优化 i+=1, 已优化为自增;
* i++ 先用后加
* ++i 先加后用
*/
let i = 1
console.log(i++); // 1 语义相当于 log(i); i+=1 实际上是原地增加;
console.log(i++); // 2
console.log(i); // 3
console.log(++i); // 4
完成示例
javascriptlet i = 0, a = i++
console.log(a, i); // 0, 1
console.log(a, i++); // 0, 2
a = -i++ // -2, i=3
console.log(a,++i); // -2 4
完成c/java面试题
javascriptlet i = 0
let a = ++i + i++ + i++ + i
/**
* ++i + i++
* 1 + 1 i=2
* 2 + i++
* 2 + 2 i=3
* 4 + i
* 4 + 3 = 7 i=3
*/
console.log(a); // 7
javascriptconsole.log(100 > 200);
console.log(100 > 2000);
/**
* 隐式类型转换
* 按ASCII, 100 > '20' 20肯定大于100,应该是false.
* 注意:任何情况下,不要使用不同类型比较;
* ***** 没有意义, 会带来bug *****
*/
console.log(100 > '20'); // true
console.log(100 > '200'); // false
console.log(200 > '200'); // false
console.log(201 > '200'); // true
console.log(100 > '2000'); // false
/**
* 比较不了,不用记
*/
console.log(100 > '20a'); // false
console.log(300 > '20a'); // false
/**
* == 字符比较
* === 字符和类型比较
*/
console.log(100 == '100'); // true
console.log(100 === '100'); // false
&& || !
and or not
& | ~
javascript/**
* 是否奇数
* 左移 * 2
* 右移 / 2
*/
console.log( (5 & 1) === 1); // true 5是奇数
javascript/**
* python: 成立 if 条件 else 不成立
* 类c: 条件?成立:不成立 ; 可以嵌套, 不推荐嵌套; 方便后续维护。
*/
console.log(5>20?'大于':'小于等于');
javascript/**
* , 参数
* , 表达式
*/
console.log(1, 2);
console.log('finished-------1--- ');
// , 表达式 相当于 let a=1; let b = 2
let a = 1, b = 2
// ; 代码分隔
let c = 1; d = 2;
/**
* 连续赋值 从左到右的优先级
* = > 三目 > 逗号
* */
let e = 1, f = 2, g = e++ > f ? 't' : 'f'
console.log(e, f, g);
console.log('finished-----2----- ');
/**
* test函数调用
* 逗号优先级最低,最终就是返回e.
*
* 表达式是有值的~~~~~~~~
* 逗号表达式的值,取决于最后一个表达式的值;
* 赋值表达式的值,取决于变量的值。
*/
function test() {
return e = 1, f = 2, g = e++ > f ? 't' : 'f'
}
console.log(test()); // 逗号表达式,就是最后一个。最后一个是赋值表达式,就是g变量的值; 结果 是f
console.log('finished------3---- ');
/**
* let, var, const 作用域
* 函数外定义, 在函数中也可以见。 全局变量
* 函数内定义,在函数外不可见。 作用域在函数中, 局部变量,局部常量
*
* j 是隐式声明(因为外面没有定义j,才是隐式定义; 如果外面定义let j 就是修改全局变量),全局变量; 会造成环境污染。以后框架是严格模式,压根写不了。
* h,i 是外层的作用域,也相当于全局变量
*
*/
let h = 1, i = 2
function test1() {
console.log(h, i, '=====test1===='); // 1 2 =========
let k = 3
var kk = 3
const kkk = 3
return null, h + i, j = h++>i?'t': 'f'
}
console.log(test1()); // 表达式的值,逗号最后1个,变量的值 ; f
console.log(j); // f 全局变量
console.log(h); // 2 全局变量
console.log(i); // 2 全局变量
// console.log(k); // ReferenceError: k is not defined
// console.log(kk); // ReferenceError: kk is not defined
// console.log(kkk); // ReferenceError: kkk is not defined
console.log('finished------4---- ');
/**
* 外面定义的let, 内部可以访问;内部定义的let外部不可以访问;
*
* 内部隐式定义修改,就是直接修改的外部的变量。
*/
let l = 1, m = 2, n = 3
function test2() {
console.log(l, m, '=====test2===='); // 1 2 =========
let o = 3
return null, l + m, n = l++>m?'t': 'f'
}
console.log(test2());
// console.log(o); // 访问不到
console.log(n); // test2函数外部的let
console.log(l, m); // 2, 2
console.log('finished------5---- ');
/**
* 外层let和内层let,同时使用let
* 就可以看到同一个变量有作用域了
*/
let cc = 3
function test3() {
let cc = 4 // python直接定义,为使用当前作用域的变量。javascript即当前这种方法类似python的方法。
console.log(cc); // 4
return cc
}
console.log(test3()); // 4
console.log(cc); // 3
console.log('finished------6---- ');
javascript1 2
finished-------1---
2 2 f
finished-----2-----
f
finished------3----
1 2 =====test1====
f
f
2
2
finished------4----
1 2 =====test2====
f
f
2 2
finished------5----
4
4
3
finished------6----
javascript/**
* typeof 类似 type
* instanceof 类似 isinstance
* 字面实例,和new实例不一样。instanceof只能识别new
*
* instaceof 和 typeof使用方法不一样,typeof === 字符串。instanceof与new比较, 这个就是语言兼容
*
* new的是对象,统一需要大写开头
* */
console.log(typeof a); // undefined
// 字面量直接定义不能这样方式
console.log('abc' instanceof String); // false
console.log(1 instanceof Number); // false
console.log(typeof 'abc' === "string"); // true
console.log(typeof 1 === 'number'); // true
// c/c++/java 一致的,必须new
console.log(new Number(100) instanceof Number); // true
console.log(new String(`abc`) instanceof String); // true
let x = new Number(100)
console.log(typeof x); // object
let y = new Object()
console.log(typeof y) // object
javascripta = 1
var b = 2
let c = 3
const d = 4
let obj = {
x: 100,
"y": 100,
}
console.log(a, b, c, d); // 1 2 3 4
console.log('============= 1 ==============');
/**
* 删除 delete 标识符或关键字
* true 删除成功
* false 删除失败
*/
console.log(delete a); // true
console.log(delete b); // false
console.log(delete c); // false
console.log(delete d); // false
console.log(b, c, d); // 2 3 4
console.log(obj.x, obj.y); // 100 100
console.log(delete obj.x); // true
console.log(delete obj.y); // true
console.log(obj); // {}, 注意 {} [] 当真
console.log(obj.x, obj.y); // undefined undefined
console.log('============= 2 ==============');
/**
* 有关键字定义,不可以删除
* 没有关键字定义,可以删除
*/
obj1 = new Object()
console.log(delete obj); // false
console.log(delete obj1); // true
console.log('============= 3 ==============');
/**
* 内建函数库,是否可以删除
*/
console.log(delete Math.floor); // true
console.log(delete Math.PI); // false
console.log(delete Math); // true
// console.log(Math.pow(2, 4)); // ReferenceError: Math is not defined
console.log('============= 4 ==============');
/**
* 数组删除
* 删除后索引的值undefined, 索引不会改变
*
0 1
1 3
2 5
3 7
4 9
true
0 1
1 3
2 undefined // 这个就是删除的值,就是悬空值,undefined
3 7
4 9
*/
let arr = [1, 3, 5, 7, 9]
console.log(arr.length); // 5
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
}
console.log(delete arr[2]);
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
}
console.log('============= 5 ==============');
/**
* 数组定义
* [] 方便
* new Array("item1", "item2", "item3", 'item4')
*/
let arr2 = new Array(1, 3, 5, 7, 9)
console.log(arr2.length); // 5
for (let i = 0; i < arr2.length; i++) {
console.log(i, arr2[i]);
}
console.log(delete arr2[2]);
for (let i = 0; i < arr2.length; i++) {
console.log(i, arr2[i]);
}
console.log('============= 6 ==============');
javascript/**
* in操作符不等价于python的in操作。不是判断元素
* 是判断 属性是否在对象中
*
* javascript会将索引和值构建为 属性:值 对,内建有length
*/
let arr = [1, 3, 5, 7, 9]
console.log(arr.length); // 5
console.log(0 in arr); // true
console.log(1 in arr); // true
console.log(3 in arr); // true
console.log(5 in arr); // false
console.log(2 in arr); // true
console.log('length' in arr); // true
console.log('============== 1 ======================');
/**
* 对象in
*/
let obj = {
a: 1,
b: 'abc'
}
// console.log(a in obj); // a全局变量是否在对象中 ReferenceError: a is not defined
console.log('a' in obj); // true
console.log('============== 2 ======================');
/**
* 数组定义
* [] 方便
* new Array("item1", "item2", "item3", 'item4')
*/
let arr2 = new Array(1, 3, 5, 7, 9)
console.log(arr2.length); // 5
console.log(0 in arr2); // true
console.log(1 in arr2); // true
console.log(3 in arr2); // true
console.log(5 in arr2); // false
console.log(2 in arr2); // true
console.log('length' in arr2); // true
console.log('============= 3 ==============');
由高到低
. [] () new 单目运算: ! ~ - + ++ -- typeof void delete 双目: * / % + - << >> >>> 比较: < <= > >= in instanceof == != === !== & ^ | 逻辑: && || 三目: ? : 赋值 = += -= *= /= %= <<= >>= >>>= &= ^= |= 逗号 ,
单目 > 双目 > 三目 > 赋值 > 逗号
算术,逻辑,生成器表达式
javascript
/**
* 生成器
* 与python不同,支持yield需要在function 和函数名之间加*号,不是指针的概念
*/
function * test() {
let c = 0
while (true) {
yield c++ // 没有*号,SyntaxError: Unexpected identifier
}
}
let x = test()
console.log(x);
console.log(x.next()); // yield值 0
console.log(x.next()); // yield值 1
console.log(x.next()); // yield值 2
console.log('============= 1 =============');
function* test1() {
let x = 0, y = 7
while (1) {
yield x++
if (!y--) {
return 100
}
}
}
let xx = test1()
console.log(xx.next()); // 0 x=1
console.log(xx.next()); // 当next时,会从上一个yield向下执行,!7不进入, 返回1; x=2 y=6
console.log(xx.next()); // 当next时,会从上一个yield向下执行,!6不进入, 返回2; x=3 y=5
console.log(xx.next()); // 当next时,会从上一个yield向下执行,!5不进入, 返回3; x=4 y=4
console.log(xx.next()); // 当next时,会从上一个yield向下执行,!4不进入, 返回4; x=5 y=3
console.log(xx.next());// 当next时,会从上一个yield向下执行,!3不进入, 返回5; x=6 y=2
console.log(xx.next());// 当next时,会从上一个yield向下执行,!2不进入, 返回6; x=7 y=1
console.log(xx.next());// 当next时,会从上一个yield向下执行,!1不进入, 返回7; x=8 y=0 { value: 7, done: false }
console.log(xx.next());// 当next时,会从上一个yield向下执行,!0进入返回100, x=9 y=-1 { value: 100, done: true } return之后,done就true, 后面不进行运算
console.log(xx.next());// 当next时,会从上一个yield向下执行,!-1不进入, 返回-1, x=10 y=-2 { value: undefined, done: true }
if (!-1) {
console.log('enter');
} else {
console.log('no');
}
console.log('============= 2 =============');
javascript/**
*
单分支
if (cond1) {
}
多分支
if (cond1) {
} else if (cond2) {
}
if (cond1) {
} else if (cond2) {
} else {
}
等价true
false
非0数值
字符
[], [1,2]
{}, {a:1}
等价false
false
undefined
null
NaN
switch (variable) {
case value1:
xxx
break
case value2:
xxx
break
...
case valueN:
xxx
break
default:
xxx
//break
}
如果不break, 就向下执行
好的习惯,就每一个加break;
实现值 或 5 或 4; 不能写 case 5 || 4
case 5:
case 4:
xxx
break
*/
let x = 5 // 4 other
x = 1 // 1 3
switch (x) {
case 0:
console.log(0);
case 1:
console.log(1);
case 3:
console.log(3);
break
case 5:
case 4:
console.log(4);
default:
console.log('other');
//break
}
遍历索引,number类型
遍历属性, string类型
javascript/**
* for索引
*
* 第1段,第2段:为真先循环,后第3段;
* 第2段假,结束循环
*/
// 1. 0, 小于5, 执行语句, 打印0
// 2. i++ => i=1, i< 5, 1
// 2
// 3
// 4
// i++ => i= 5, i<5, 不进入循环体
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log('---');
for (let i = 0; i < 5; i++) {
console.log(i++);
}
console.log('========== 1 偶数 0 2 4 =============');
for (let i = 0; i < 5; i++) {
console.log(++i);
}
console.log('========== 2 奇数 1 3 5 =============');
for (let i = 0; i < 5; i++) {
console.log(i + 1);
}
console.log('========== 3 0-4 -> 1 2 3 4 5 =============');
// 0 1 2 3 4
for (let i = 0; i < 5; i += 1) {
console.log(i);
}
console.log('========= 4');
// 0 2 4
for (let i = 0; i < 5; i += 2) {
console.log(i);
}
console.log('========= 5');
// 第3段,i++或++i 均一样,表达式的值并不会使用,只是执行
for (let i = 0; i < 5; ++i) {
console.log(i);
}
console.log('========= 6');
/**
* 数字属性 0 number 1
*/
let arr = [1, 3, 6, 7]
for (let i = 0; i < arr.length; ++i) {
console.log(i,typeof i , arr[i]);
}
console.log('---------------------------');
/**
* for值
*/
let y = new Array('one', 'two', `three`, "five")
for (let i of y) {
console.log(i);
}
console.log('========== 6 遍历值 =============');
/**
* for属性
* 取的是字符串 a string 1 undefined
* 内部存的是字符串
* */
let obj = {
a: 1,
b:'abc'
}
for (let y in obj) {
// 属性,属性类型, 变量y为属性的值, y属性
console.log(y,typeof y,obj[y],obj.y);
}
javascript/**
* 两个循环变量
*/
for (let i = 0, j = 9; i < 10; i++, j--) {
console.log(i, j, i*j);
}
console.log('-----------');
javascript
/**
* 死循环
*/
for (; ;) {
console.log('hello world');
}
while(1) {
}
javascript/**
while (cond) {
}
cond为真进入循环
*
*
do {
} while (cond)
先循环一次, 条件为真,才继续执行
*/
// 10 打印9; 1 打印0, x=0; x--,取0不满足,但是x已减1 ~~~~~~~~~~~~~
let x = 10
while (x--) {
console.log(x);
}
console.log('9 到 0 ');
console.log(x,'~~~~~~~~~~~~~');
// x = -1
// 打印-1
// -1< 10 打印0
// 0 打印 1
// 9 打印10
// 10 不打印,但是运算了,x为11
do {
console.log(x);
} while (x++ < 10)
console.log(x,' ~~~~~~~~~~~~~');
console.log('-1 到 10');
javascriptfor (let i = 1; i < 10; i++) {
str = ''
for (let j = 1; j <= i; j++) {
if (i * j < 10) {
str += `${i} * ${j} = ${i*j} `
} else {
str += `${i} * ${j} = ${i*j} `
}
}
console.log(str);
}
隐式声明为全局
函数/if块, 局部变量 向内穿透, var/let/const. 向外不可见; 特殊: if块的var也会变全局, 向外可见;
javascript
/**
* 函数作用域
* 函数中,if或多级if中, 隐式定义,均为全局变量;
* 函数中var/const/let定义均为局部变量; ~~ 向内穿透, 向外不可见 ~~
* if块中,const/let定义为局部变量 ~~ 向内穿透, 向外不可见 ~~; var为全局变量; python中没有块的概念
*/
function test() {
a = 100; // 隐式变成全局, 不推荐
var b = 200; // var可以在函数中, 不能变全局
let c = 300;
}
test()
console.log(a);
// console.log(b); // 不可见
// console.log(c); // 不可见
console.log('----------------');
if (1) {
d = 100; // 隐式变成全局, 不推荐
let e = 200;
var f = 300; // var可以在if中变全局
const g = 400
console.log(e,f,g);
}
console.log(d);
// console.log(e); // 不可见
console.log(f); // var if可以向外穿透
// console.log(g); // 不可见
console.log('`````````````````````````````');
if (1) {
h = 100;
let i = 200;
var j = 300;
const k = 400
console.log(i, j, k); // 200 300 400
{
let l = 1;
var m = 2;
const n = 3;
console.log(h,i,j,k,l,m,n,'============'); // 向内穿透 100 200 300 400 1 ============
}
}
console.log(h); // 100
// console.log(i); // 不可见
console.log(j); // 300 var if可以向外穿透
// console.log(k); // 不可见
// console.log(l); // 不可见
console.log(m); // 2 var 多级if可以向外穿透
// console.log(n); // 不可见
例题
javascriptvar j = 'jj'
var k = 'kk'
function t() {
j = 'aa'
var k = 'bb'
var z = '123'
console.log(j); // 因为外面声明了j, 修改外面的j; aa
console.log(k); // 外面var, 里面var. 里面就是不可穿透; bb
}
t()
console.log(j); // aa 穿透
console.log(k); // kk 不可穿透
/**
* var 声明提升,相当于z未赋值
*/
console.log(z); // undefined
var z
z = 'abc'
console.log(z); // abc
框架会在每个js文件前添加 "use strict"
, 隐式声明报错
javascript"use strict"
x = 500; // ReferenceError: x is not defined
javascript/**
* 抛出异常
* 类java: throw
* python: raise
*/
throw new ReferenceError(123)
异常处理比较简单, 所以一般只是记录异常
js是单线程, 抛出异常不管这个单线程就异常了。所以一般需要处理异常。
javascript/**
* 抛出异常
* 类java: throw
* python: raise
*
* 抓异常, try不可以单独使用;
try {}
catch {}
finally {}
*/
try {
throw new ReferenceError(123)
} catch (e) { /** 不能区别异常 */
console.log(e); // 异常本身
console.log(typeof e); // typeof 返回字符串
console.log(e.constructor); // 获取构造器,异常实例是类构造出来 的。 说的是类,实际看到是函数,习惯称为类: [Function: ReferenceError]
console.log(e.constructor.name); // 异常类名,字符串 ReferenceError
console.log(e.message); // 异常消息 123
console.log('+'.repeat(12));
} finally {
console.log('-'.repeat(12));
}
不抛异常类型
javascripttry {
// throw 'abc' // python才会检查抛出来的异常类型; 所以在javascript中,建议使用 throw new Error的子类, 抛出异常实例。
throw new Error('abc') // 建议
} catch (e) { /** 不能区别异常 */
console.log(e); // 异常本身
console.log(typeof e); // typeof 返回字符串
console.log(e.constructor); // 获取构造器,异常实例是类构造出来 的。 说的是类,实际看到是函数,习惯称为类: [Function: String]
console.log(e.constructor.name); // 异常类名,字符串 String
console.log(e.message); // 字符串没有异常消息
console.log('+'.repeat(12));
} finally {
console.log('-'.repeat(12));
}
js一种基于原型(Prototype)的面向对象语言, 而不是基于类的面向对象语言。基于原型、原型链来实现对象。
基于原型,构建原型链。
封装、继承、多态均可以实现。
c++, java class和instance概念, 类是一类事物抽象, 实例是类的实体。
js应用于前端,后端 nodejs.
微软的flash,有安全问题。js有沙盒。
javascript/**
* 直接定义
* 写对象名, 名为key, 值为值
* [对象名]:对象名,值为key, 值为值
* 函数没有写function关键字,只有名() {}, 名为key, 函数对象为值
*/
const fn = () => { console.log('ABC'); }
let x = 100
console.log(typeof fn, typeof x); // function number
let obj = {
a: 1,
b: 'abc',
'c': [],
// fn: fn, // 'fn': fn 右边是函数对象; 相当于fn
fn, // 等价 fn:fn, 等价 'fn': fn
show: () => { console.log('123'); },
x, // x:x 或 'x': x
[x]: x, // 取变量值:x, 100:x
test() {
console.log('7');
} // test: test, 'test': test
}
console.log(obj); /**
{
'100': 100,
a: 1,
b: 'abc',
c: [],
fn: [Function: fn],
show: [Function: show],
x: 100,
test: [Function: test]
}
*/
es6之前没有类, 缺的是构造器。
js# 类使用方法 类() 就是实例 # 实现相同的过程 js给你函数, 函数() 构建实例即可
还有部分人在使用的,常用的语法,与python类似
函数名,首字母大写
this指针,类中,永远指向当前实例。
javascript/**
* ES6之前
*
* @param {*} x 参数1 数值
* @param {*} y 参数2 数值
*/
function Point(x, y) {
this.x = x // 实例属性
this.y = y
}
let p1 = Point(4, 5) // 函数调用
console.log(p1, typeof p1); // undefined undefined
let p2 = new Point(4, 5) // 构造实例
console.log(p2, typeof p2, p2.x); // Point { x: 4, y: 5 } object
/**
* 写继承
* 没有(像python)直接写哪个是父类,需要手工调用父类
* 借用函数的call方法,把this(Point3D实例)传递给父类。
* @param {*} x
* @param {*} y
* @param {*} z
*/
function Point3D(x, y, z) {
Point.call(this,x, y) // python中,直接调用父类,就需要把self传递给父类;python是显式传递self;c/c++/java不需要显式传递;这里借用函数的call方法,把this(Point3D实例)传递给父类。
this.z = z
}
let p3 = new Point3D(7, 8, 9)
console.log(p3, p3.constructor); // Point3D { x: 7, y: 8, z: 9 } [Function: Point3D]
Point.call(this,x, y)
由于这个是函数Point()调用,不是实例调用。所以函数中this是全局对象, Point.call(this,x,y) 就将Point函数中的this修正为传入的this。python中,也一样: Point(self,x,y)javascript/**
* ES6之后 class
* 实例化没有new就报错,改进了
*
*/
class Point {
constructor(x, y) {
this.x = x // this指针,类中,永远指向当前实例。
this.y = y
} // __init__(x,y)
}
// 新语法,不加new就会异常
let p1 = new Point(4, 5)
console.log(p1); // Point { x: 4, y: 5 }
// 使用父类的构造器
class Point3D1 extends Point {}
let p3 = new Point3D1(4, 5, 6) // Point3D1 { x: 4, y: 5 }
console.log(p3);
class Point3D extends Point {
constructor(x, y, z) {
super(x, y) // python中可以将调用父类__init__在最后一句;而javascript必须先构造,才可以this.z
this.z = z
}
}
let p4 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 }
console.log(p4);
diff
/**
* ES6之前
*
* @param {*} x 参数1 数值
* @param {*} y 参数2 数值
*/
function Point(x, y) {
this.x = x // 实例属性
this.y = y
+ this.showMe = () => {console.log(this.x, this.y);}
}
let p1 = Point(4, 5) // 函数调用
console.log(p1, typeof p1); // undefined undefined
let p2 = new Point(4, 5) // 构造实例
console.log(p2, typeof p2, p2.x); // Point { x: 4, y: 5 } object
+p2.showMe() // 4 5
/**
* 写继承
* 没有直接写哪个是父类,需要手工调用父类
* 借用函数的call方法,把this(Point3D实例)传递给父类。
* @param {*} x
* @param {*} y
* @param {*} z
*/
function Point3D(x, y, z) {
Point.call(this,x, y) // python中,直接调用父类,就需要把self传递给父类;python是显式传递self;c/c++/java不需要显式传递;这里借用函数的call方法,把this(Point3D实例)传递给父类。
this.z = z
}
let p3 = new Point3D(7, 8, 9)
console.log(p3, p3.constructor); // Point3D { x: 7, y: 8, z: 9 } [Function: Point3D]
+p3.showMe() // 7 8
问题:子类p3实例只有7,8没有9; 添加新的方法,覆盖即可;
diff/**
* ES6之后 class
* 实例化没有new就报错,改进了
*
*/
class Point {
constructor(x, y) {
this.x = x // this指针,类中,永远指向当前实例。
this.y = y
} // __init__(x,y)
+ showMe() {
+ // c/java不用 明着传this
+ // python需要明着传this
+ console.log(this.x, this.y);
+ }
}
// 新语法,不加new就会异常
let p1 = new Point(4, 5)
console.log(p1); // Point { x: 4, y: 5 }
+p1.showMe() // 4 5
class Point3D1 extends Point {}
let p3 = new Point3D1(4, 5, 6) // Point3D1 { x: 4, y: 5 }
console.log(p3);
+p3.showMe() // 4 5
class Point3D extends Point {
constructor(x, y, z) {
super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z
this.z = z
}
+ showMe() {
+ console.log(this.x, this.y, this.z);
+ }
}
let p4 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 }
console.log(p4);
+p4.showMe() // 4 5 6
新语法,继承后,修改showMe
diff/**
* ES6之后 class
* 实例化没有new就报错,改进了
*
*/
class Point {
constructor(x, y) {
this.x = x // this指针,类中,永远指向当前实例。
this.y = y
} // __init__(x,y)
showMe() {
// c/java不用 明着传this
// python需要明着传this
console.log(this.x, this.y);
}
}
// 新语法,不加new就会异常
let p1 = new Point(4, 5)
console.log(p1); // Point { x: 4, y: 5 }
p1.showMe() // 4 5
class Point3D1 extends Point {}
let p3 = new Point3D1(4, 5, 6) // Point3D1 { x: 4, y: 5 }
console.log(p3);
p3.showMe() // 4 5
class Point3D extends Point {
constructor(x, y, z) {
super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z
this.z = z
}
+ showMe() {
+ super.showMe() // super调用父类方法, 实现了较为复杂的实现。我们只需要下面完成自己的逻辑。 自动解决this问题
+ console.log(this.z);
+ }
}
let p4 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 }
console.log(p4);
+p4.showMe() // 4 5 6
以上全部定义为方法,子类方法会覆盖父类的方法。
javascript
class Point {
showMe() {
// c/java不用 明着传this
// python需要明着传this
console.log(this.x, this.y,'**');
}
constructor(x, y) {
this.x = x // this指针,类中,永远指向当前实例。
this.y = y
// this.showMe = () => {console.log(this.x,'//');}
} // __init__(x,y)
}
// 新语法,不加new就会异常
let p1 = new Point(4, 5)
console.log(p1); // Point { x: 4, y: 5 }
// p1.showMe() // 4 构建器中优先
class Point3D extends Point {
constructor(x, y, z) {
super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z
this.z = z
// this.showMe = () => {
// console.log(this.x, this.y, this.z,'++');
// }
}
showMe() {
super.showMe()
console.log(this.x, this.y, this.z,'--');
}
}
let p3 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 }
console.log(p3);
p3.showMe() // 4 5 6 ++
class Point { showMe() { // c/java不用 明着传this // python需要明着传this console.log(this.x, this.y,'**'); } constructor(x, y) { this.x = x // this指针,类中,永远指向当前实例。 this.y = y this.showMe = () => {console.log(this.x,'//');} } // __init__(x,y) } // 新语法,不加new就会异常 let p1 = new Point(4, 5) console.log(p1); // Point { x: 4, y: 5 } // p1.showMe() // 4 构建器中优先 class Point3D extends Point { constructor(x, y, z) { super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z this.z = z // this.showMe = () => { // console.log(this.x, this.y, this.z,'++'); // } } // showMe() { // super.showMe() // console.log(this.x, this.y, this.z,'--'); // } } let p3 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 } console.log(p3); p3.showMe() // 4 //
父类属性优先
class Point { showMe() { // c/java不用 明着传this // python需要明着传this console.log(this.x, this.y,'**'); } constructor(x, y) { this.x = x // this指针,类中,永远指向当前实例。 this.y = y this.showMe = () => {console.log(this.x,'//');} } // __init__(x,y) } // 新语法,不加new就会异常 let p1 = new Point(4, 5) console.log(p1); // Point { x: 4, y: 5 } // p1.showMe() // 4 构建器中优先 class Point3D extends Point { constructor(x, y, z) { super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z this.z = z // this.showMe = () => { // console.log(this.x, this.y, this.z,'++'); // } } showMe() { super.showMe() console.log(this.x, this.y, this.z,'--'); } } let p3 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 } console.log(p3); p3.showMe() // 4 //
父类属性优先
javascript
class Point {
showMe() {
// c/java不用 明着传this
// python需要明着传this
console.log(this.x, this.y,'**');
}
constructor(x, y) {
this.x = x // this指针,类中,永远指向当前实例。
this.y = y
this.showMe = () => {console.log(this.x,'//');}
} // __init__(x,y)
}
// 新语法,不加new就会异常
let p1 = new Point(4, 5)
console.log(p1); // Point { x: 4, y: 5 }
// p1.showMe() // 4 构建器中优先
class Point3D extends Point {
constructor(x, y, z) {
super(x, y) // python中可以将调用父类init在最后一句;而javascript必须先构造,才可以this.z
this.z = z
this.showMe = () => {
console.log(this.x, this.y, this.z,'++');
}
}
showMe() {
super.showMe()
console.log(this.x, this.y, this.z,'--');
}
}
let p3 = new Point3D(4, 5, 6) // Point3D { x: 4, y: 5, z: 6 }
console.log(p3);
p3.showMe() // 4 5 6 ++
不是python静态方法
javascript/**
* 静态方法
* java, javascript都是如此:static 定义 静态方法和静态属性,均 只有类访问,静态方法或属性中的this是指向类。
*
* 实例方法,不加static. 其中this是类构造实例本身。
*
* python中,类的属性,类和实例可以访问。
* 静态方法,类和实例可以访问
* 类方法,类和实例可以访问
* 实例方法,需要传递this, 实例可以访问。
*/
class Point {
// 类的; javascript中,类的属性不是大家的;python是大家的;
// 静态的,只能通过类访问
static z = 123
// 实例化
constructor(x, y) {
this.x = x
this.y = y
console.log('~'.repeat(12));
}
// 实例的
showMe() {
console.log('+'.repeat(12));
// 实例看不到 类的z
console.log(this.x, this.y, this.z)
}
// 类使用,类调用时,this就是类。
static nowZ() {
console.log(this.z, '~@#@#'); // 123 ~@#@#
}
}
console.log(Point.z); // 类的静态属性
Point.nowZ() // 类的静态方法
console.log('_++以上类的属性和方法。以下是实例的方法和属性+');
let p1 = new Point(3, 5)
console.log(p1, p1.constructor, p1.x); // Point { x: 3, y: 5 } [class Point]
p1.showMe() // 3 5 undefined
// Point.showMe() // TypeError: Point.showMe is not a function 没有实例,不能this. 类不能访问实例的方法
// p1.showZ() // TypeError: p1.showZ is not a functio 实例不能访问静态的方法;类的方法;
console.log(p1.z); // undefined
静态方法中的this,指向当前类。
构造器, 实例方法中的this, 指向实例。
this可以动态变化, 实例调用的方法,方法中的this, 是前面的实例。
javascript/**
* 字面定义 实例
* this, globalThis 表示全局对象。
* 换this,动态绑定:实例调用的方法,方法中的this, 是前面的实例。
*/
let tom = {
name: 'tome',
getName: function() {
console.log(this === globalThis, this.name);
},
}
console.log(tom.name);
tom.getName() // false tome 表示this是当前实例,不是全局对象。 ******* 实例调用的方法,方法中的this就是实例。实例与方法绑定 动态绑定
// 换this
let jerry = {
name: 'jerry',
}
console.log(jerry.name);
/**
* 修改方法的实例
*/
// jerry.getName() // TypeError: jerry.getName is not a function
tom.getName.call(jerry) // false jerry
console.log('='.repeat(13))
/**
* 全局方法
*/
const getName = function() {
console.log(this === globalThis, this.name);
}
// 全局函数,this就是全局
getName() // true undefined
name = '123' // 隐式定义,直接挂载在global上
getName() // true 123
console.log('>'.repeat(13))
/**
* 实例中放全局方法,方法中的this,是实例的this.
* ******* 实例调用的方法,方法中的this就是实例。实例与方法绑定 动态绑定
*/
let a = {
name: 'a',
getName, // 等价 'getName': getName
}
a.getName() // false a
let b = {
name: 'b', getName
}
b.getName() // false b
javascript/**
* 全局方法
*/
const getName = function() {
console.log(1, this === globalThis, this.name);
return function() {
console.log(2, this === globalThis, this.name);
}
}
// 全局函数,this就是全局
getName()() // true undefined
name = 'mykernel' // 隐式定义,直接挂载在global上
getName()() // true 123
console.log('>'.repeat(13))
/**
* 实例中放全局方法,方法中的this,是实例的this.
* ******* 实例调用的方法,方法中的this就是实例。实例与方法绑定 动态绑定
*/
let a = {
name: 'a',
getName, // 等价 'getName': getName
}
a.getName()() // 1 false a , 2 true 123
const inner = a.getName() // 1 false a; 返回一个临时的函数
inner() // 函数调用, 没有实例调用, 第2次的globalThis就是全局函数
console.log('@'.repeat(30));
let b = {
name: 'b',
getName: function() {
console.log(1, this === globalThis, this.name);
return function() {
console.log(2, this === globalThis, this.name);
}
}, // 等价 'getName': getName
}
b.getName()() // 第2次是函数调用,不是实例调用,所以this就是全局的实例
javascript/**
* 解决非动态绑定
*/
var getName = function() {
console.log(1, this === globalThis, this.name);
return function() {
console.log(2, this === globalThis, this.name);
}
}
// 全局函数,this就是全局
getName()() // true undefined
name = 'mykernel' // 隐式定义,直接挂载在global上
getName()() // true 123
console.log('>'.repeat(13))
/**
* 缺什么补什么
* that法
*/
getName = function() {
console.log(1, this === globalThis, this.name);
return function(that) {
console.log(2, this === globalThis, that.name);
}
}
let a = {
name: 'a',
getName, // 等价 'getName': getName
}
a.getName()(a) // 1 false a , 2 true 123
var inner = a.getName() // 1 false a; 返回一个临时的函数
inner(a) // 函数调用, 没有实例调用, 第2次的globalThis就是全局函数
console.log('@'.repeat(30));
/**
* call(this) apply(this) Function类型,由function定义的函数。均有call/apply方法。
* fn() => fn.call(this); fn.call(this,...array) 列表 常用, 方便写。
* fn() => fn.apply(this); fn.apply(this, array) 数组
*/
getName = function() {
console.log(1, this === globalThis, this.name);
return function(x,y) {
console.log(2, this === globalThis, this.name,x,y);
}
}
a = {
name: 'a',
getName, // 等价 'getName': getName
}
a.getName().call(a,4,3) // fn() => fn.call(this) ,前者this是非动态加载的this, 全局this; fn.call(this) 将可以替换其中的this为送进来的实例
var inner = a.getName()
inner.apply(a,new Array(3,3))
console.log('*'.repeat(30));
let b = {
name: 'b',
getName: function() {
console.log(1, this === globalThis, this.name);
return function() {
console.log(2, this === globalThis, this.name);
}
}, // 等价 'getName': getName
}
b.getName()() // 第2次是函数调用,不是实例调用,所以this就是全局的实例
函数bind之后,修改this, 并返回函数
javascript/**
* fn() = 动态绑定this => fn.bind(this)()
*/
let b = {
name: 'b',
getName: function() {
console.log(1, this === globalThis, this.name);
return function(x,y) {
console.log(2, this === globalThis, this.name,x,y);
}
}, // 等价 'getName': getName
}
b.getName()() // 第2次是函数调用,不是实例调用,所以this就是全局的实例
let x = b.getName().bind(b)
console.log(x, typeof x);
x(3,4) // 2 false b 3 4
nodejs中
javascript
const getName = function() {
console.log(1, this === globalThis, this.name); // 1 false a
return function(x, y) {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 false a ; 2 true undefined undefined undefined
let inner = a.getName() // 1 false a
inner.bind(b)(6, 6) // 2 false b 6 6
nodejs中,内层函数变箭头函数
箭头函数的this, 是创建函数的一刹那决定的。
内层函数是临时创建的, 环境中的this,利用了当前作用域的this。
javascriptname = 'mykernel.cn'
const getName = function () {
console.log(1, this === globalThis, this.name); // 1 false a
return (x, y) => {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 false a ; 2 false a undefined undefined
// let inner = a.getName() // 1 false a
// inner.bind(b)(6, 6) // 2 false b 6 6
nodejs中,不能用
javascriptglobalThis.name = 'mykernel'
const getName = () => {
console.log(1, this === globalThis, this.name);
return function (x, y) {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 false undefined; 2 true mykernel undefined undefined
浏览器中
javascriptglobalThis.name = 'mykernel'
const getName = () => {
console.log(1, this === globalThis, this.name);
return function (x, y) {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 false mykernel; 2 true mykernel undefined undefined
nodejs中有问题, 箭头函数在浏览器中使用
javascriptglobalThis.name = 'mykernel'
const getName = () => {
console.log(1, this === globalThis, this.name);
return (x, y) => {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 false undefined; 2 false undefined undefined undefined
浏览器中
javascriptglobalThis.name = 'mykernel'
const getName = () => {
console.log(1, this === globalThis, this.name);
return (x, y) => {
console.log(2, this === globalThis, this.name, x, y);
}
}
let a = {
name: 'a',
getName
}
let b = {
name: 'b',
}
a.getName()() // 1 true "mykernel"; 2 true "mykernel" undefined undefined
替换this, 创建一刹那 this定死了, 改不了。call, apply ,bind均改不了。
构造器 类.prototype 与 实例.__proto__ 一样
相同类,不同实例。可以通过类.prototype.属性,所有实例共享数据。
不同类,不同实例。可以通过Object.prototype.属性,任何类任何实例共享数据。
javascriptlet tom = {
name: 'tom'
} // new Object
tom.__proto__ // [[prototype]] Object.prototype
console.dir(tom.__proto__ === Object.prototype) // true
class Person {
constructor(name) {
this.name = name
}
}
let p1 = new Person('ben')
console.log(p1.__proto__ === Person.prototype); // true
bashPerson {name: "ben"} # 实例访问属性, name有;没有自动在__proto__下面查找。
name: "ben"
__proto__:
age: 20
constructor: class Person
__proto__:
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
前端:
展开语法
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax
javascript// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax
/**
* 列表解构
*/
var parts = [1, 2]
var lyrics = [0, ...parts, 3, 4, 5]
console.log(lyrics); // [ 0, 1, 2, 3, 4, 5 ]
console.log([...parts]); // [ 1, 2 ]
/**
* 参数解构
*/
function test(a, b) {
return a + b
}
console.log(test()); // undefined + undefined = NaN
function f(x, y, z) {
console.log(x + y + z);
}
f(4, 5, 6, 7) // 15
var args = [2, 3, 4]
f(...args) // 9
/**
* 数组解构
*
* 与python不一样,逗号优先级高; c/java/c++中逗号优先级低于=号,所以赋值先执行。
*
* js解构,要求两边写一样
* js解构,...args只能放最后一个
*/
let arr = [1, 3, 5]
let x, y, z, n = arr // 与python不一样,逗号优先级高; c/java/c++中逗号优先级低于=号,所以赋值先执行。
console.log(x, y, z, n); // undefined undefined undefined [ 1, 3, 5 ]
// 写多了
let [a, b, c, d] = arr // let d是悬空的,undefined
console.log(a, b, c, d); // 1 3 5 undefined
// 写少了
let [e] = arr
console.log(e); // 1 解构第1个参数; python中不能这样解构
// 正常解构数组
let [ff, gg, hh] = arr // python也可以这样解构
console.log(ff, gg, hh); // 1 3 5
// 忽略变量
let [, ee, ] = arr
console.log(ee); // 3
let [, , eee, ] = arr
console.log(eee); // 5
// js默认值, 没有关键字传参
let [aa = 111, bb, cc, dd, ddd = 300] = arr // dd, ddd 悬空,但是ddd有默认值
console.log(aa, bb, cc, dd, ddd); // 1 3 5 undefined 300
// 解构,聚合
let [aaa, ...args2] = arr
console.log(aaa, args2); // 1 [3,5]
/**
* python支持这样解构数组
In [1]: arr = [1,3,5,7]
In [2]: x,*args,y = arr
In [3]: x
Out[3]: 1
In [4]: y
Out[4]: 7
In [5]: args
Out[5]: [3, 5]
*/
// js 不支持这样解构数组;
// ...args 只能在最后一个参数
//
// let [aaaa, ...arg4, b] = arr // SyntaxError: Rest element must be last element
// console.log(aaaa,args4,b);
console.log('复杂的数组解构');
let arr1 = [1, [2, 3], 4]
let [xx, yy, zz, xyz] = arr1
console.log(xx, yy, zz, xyz); // 1 [ 2, 3 ] 4 undefined
let [xxx, [yyy, zzz], xyzz] = arr1
console.log(xxx, yyy, zzz, xyzz); // 1 2 3 4
const [ca, cb] = arr1
console.log(ca, cb); // 1 [ 2, 3 ]
const [cm, , , , , cn] = arr1
console.log(cm, cn); // 1 undefined
const [cx, ...cargs] = arr1
console.log(cx, cargs); //1 [ [ 2, 3 ], 4 ]
/**
* 对象解构
*
* python中没有这样的概念, 传参时,**kwargs
*/
let o1 = {
oa: 1,
ob: 2,
oc: 3
}
console.log(o1); // { a: 1, b: 2, c: 3 }
// 获取a,b, c
console.log(o1.oa, o1.ob, o1.oc); // 1 2 3
console.log(o1['oa'], o1[`ob`], o1["oc"]); // 1 2 3
// 获取没有的 悬空
console.log(o1.oz, o1['oz']); // undefined
// 别名解构
var { oa: ox, ob: oy, oc: oz } = o1
console.log(ox, oy, oz); // 1 2 3
// 不存在key 的解构
var { ox, oy, oz } = o1
console.log(ox, oy, oz); // undefined undefined undefined
// 同属性名 的解构
var { oa, ob, oc } = o1
console.log(oa, ob, oc); // 1 2 3
// 更少key
var { oa } = o1
console.log(oa); // 1
// 更多key
var { oa, ob, oc, oe } = o1
console.log(oa, ob, oc, oe); // 1 2 3 undefined
// key顺序乱序, 按名称对应
var { ob, oa, oc, oe } = o1
console.log(oc, ob, oa, oe); // 3 2 1 undefined
// key 默认值, 存在不使用默认值。不存在使用默认值。
var { ob = 222, oa, oc, oe = 300 } = o1
console.log(oc, ob, oa, oe); // 3 2 1 300
// 别名解构 默认值
var { oa: ox, ob: oy, oc: oz, ot: ott = 300 } = o1
console.log(ox, oy, oz, ott); // 1 2 3 300
/**
* 复杂解构
*/
let o2 = {
a: 1,
'b': [{ a: 11 }, { a: 111 }],
"o2c": 3
}
// 不解构,取3个a
console.log(o2.a, o2.b[0].a, o2.b[1].a); // 1 11 111
// 利用解构,一次提取出3个a
var { a: o2a1, b: [{ a: o2a2 }, { a: o2a3 }], o2c } = o2
console.log(o2a1, o2a2, o2a3, o2c); // 1 11 111 3
javascript/**
* 对象的操作
* 类似Python方法
*
*
* keys是标准方法; values/entries是实验性方法;
* Objects.keys => python: d.keys
* Object.values => python: d.values
* Object.entries => python: d.items
*
* Object.assign
*/
let obj = {
a: 1,
b: 2,
c: 3
}
// 取属性, for in, in取属性 ; for of 元素;
for (let i in obj) {
console.log(i, obj[i]); // a 1; b 2; c 3
}
// Object.keys 取对象属性名数组
console.log(Object.keys(obj)); // [ 'a', 'b', 'c' ]
console.log(Object.values(obj)); // [ 1, 2, 3 ]
console.log(Object.entries(obj)); // [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]
// Object.assign
// 把obj对象弄到o2, o2的对象返回出来
let o2 = {}
let o1 = Object.assign(o2, obj)
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }
console.log(obj == o1); // false; 自定义对象比较,就是内存地址比较
console.log(obj === o1); // false
console.log(o1 == o2); // true
/**
* 配置
* 越在后面,配置会覆盖
*/
let obj1 = {
port: 8000,
}
let o3 = {
port: 9901
}
let o4 = Object.assign(o3, obj1, { port: 9000, domain: 'www.magedu.com' })
console.log(o4); // { port: 9000, domain: 'www.magedu.com' }
5.2.4 字符串操作,通用
javascript/**
* 数组操作
* push => python: append+extend
* pop
* slice 切片 查询
* splice 切片 查询并删除, 删除后索引不在了; delete删除后索引还在,值不在。
* splice(start,stop) 删除 [start, stop] 索引均包含
* splice(start,stop,'replace') 删除, 插入1个到索引start
* splice(1,0,'replace') 不删除, 插入到索引1
* splice(start,stop,'replace1', 'replace2') 删除, 插入多个到索引start
*
* 数组迭代
* for 数字索引
* for in 字符属性
* for of 元素
*
* map 拿出每个元素, 修改, 直接返回新的数组 => python: map 拿出每个元素, 修改, 生成惰性迭代器
* filter 拿出元素,过滤, 直接返回新的数组 => python: filter 拿出元素,过滤, 生成惰性迭代器
* foreach 遍历数据索引和值
*/
let arr = [1, 3, 5, 8]
console.log(5 in arr); // false
// push
console.log(arr.push(9, 11)); // ...items 返回当前长度
console.log(arr); // [ 1, 3, 5, 8, 9, 11 ]
// pop
console.log(arr.pop()); // 11 从结束弹出来一个数据
console.log(arr); // [ 1, 3, 5, 8, 9 ]
// slice 切片 查询
// splice 切片 查询并删除,
console.log(arr.slice(0, 2), '-=', arr); // [ 1, 3 ] -= [ 1, 3, 5, 8, 9 ]
console.log(arr.splice(0, 2), '-=', arr); // [ 1, 3 ] -= [ 5, 8, 9 ]
/**
* delete删除索引还在,值不在。而splice删除,索引也动了。
0 5
1 8
2 9
*/
for (let i in arr) {
console.log(i, arr[i]);
}
// 取删除,替换
console.log(arr); // [ 5, 8, 9 ]
console.log(arr.splice(0, 2, 'a')); // [ 5, 8 ]
console.log(arr); // [ 'a', 9 ]
// 插入
arr.push(1, 2, 3, 4)
console.log(arr); // [ 'a', 9, 1, 2, 3, 4 ]
console.log(arr.splice(1, 0)); // []
console.log(arr); // [ 'a', 9, 1, 2, 3, 4 ]
console.log(arr.splice(1, 0, 'x')); // []
console.log(arr); // [ 'a', 'x', 9, 1, 2, 3, 4]
// 删除items, 插入元素
console.log(arr.splice(1, 2, 'm', 'n', 'o')); // [ 'x', 9 ]
console.log(arr); // [ 'a', 'm', 'n', 'o', 1, 2, 3, 4 ]
/**
* 数组迭代
[
'a', 'm', 'n', 'o',
1, 2, 3, 4
]
*/
console.log(arr);
// for 数字索引
for (let x = 0; x < arr.length; ++x) {
console.log(x, typeof x, arr[x]);
}
// for 字符属性
for (let x in arr) {
console.log(x, typeof x, arr[x]);
}
// for item
for (let x of arr) {
console.log(x);
}
// map 返回值为新列表的元素
let arr1 = [1, 3, 4]
console.log(arr1.map(x => x + 'abc')); // [ '1abc', '3abc', '4abc' ]
//虽然map支持2个参数,但是js 可以只给1个元素。
console.log(arr1.map((item, index) => item + index), '^'.repeat(12)); // [ 1, 4, 6 ]
// filter 返回值为true保留
console.log(arr1.filter(x => x - 3)); // [ 1, 4 ]
// foreach 无返回值, 原数据不变
const newArr = [] // 常量,内存地址不变
arr1.forEach((item, index) => {
console.log(item, index, '------------');
newArr.push(item + index)
})
console.log(arr1); //[ 1, 3, 4 ]
console.log(newArr); // [ 1, 4, 6 ]
console.log('~'.repeat(50));
let a1 = []
console.log(a1);
a1[5] = 20
a1[8] = 10
console.log(a1, a1.length); // [ <5 empty items>, 20, <2 empty items>, 10 ] 9
let arr2 = [2, 4, 5]
const newArr1 = [] // 常量,内存地址不变
arr2.forEach((item, index) => {
newArr1[index] = item + index
})
console.log(arr2); // [ 2, 4, 5 ]
console.log(newArr1); // [ 2, 5, 7 ]
数组 const arr = [1,2,3,4,5] 算出元素平方值, 输出平方值是偶数且大于10的值
需求
javascriptconst arr = [1, 2, 3, 4, 5]
console.log(arr.map(item => item ** 2).filter(item => item > 10 && item%2 === 0));
这样写不合适
map(item => item ** 2)
遍历,再计算。先大量计算前,过滤不合格
filter提前
javascriptconst arr = [1, 2, 3, 4, 5]
console.log(arr.filter(x => ! (x%2)).map(x=>x**2).filter(x => x > 10) );
filter之前
sqrt
x ** 0.5
javascriptconst arr = [1, 2, 3, 4, 5]
console.log(arr.filter(x => ! (x%2)).filter(x => x > Math.sqrt(10)).map(x=>x**2) );
filter聚合
javascriptconst arr = [1, 2, 3, 4, 5]
const point = 10
console.log(arr.filter(x => ! (x%2) && x > Math.sqrt(point)).map(x=>x**2) );
%比位慢 %2, x&1
奇数
javascriptconst arr = [1, 2, 3, 4, 5]
const point = 10
console.log(arr.filter(x => ! (x&1) && x > Math.sqrt(point)).map(x=>x**2) );
短路, 比较大小,比&快
javascriptconst arr = [1, 2, 3, 4, 5]
const point = 10
console.log(arr.filter(x => x > Math.sqrt(point) && ! (x&1)).map(x=>x**2) );
再高一点,2次循环,改单循环
javascriptconst arr = [1, 2, 3, 4, 5]
const point = 10
const target = []
arr.forEach(
item => {
if (item > Math.sqrt(point) && !(item & 1)) {
target.push(item**2)
}
}
)
console.log(target);
代码多了,写一起不行。
ES6之前,没有模块化。
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 遇到script标签 JS引擎, 解析为js脚本 -->
<script>
console.log('abc');
let obj = {
abc: 1000000
}
</script>
<!-- 引入 外部脚本,将自动追加到Html之下 -->
<script src="./32.js"></script>
<!-- <script>
console.log('xyz~~~~~~~~~~');
console.log(obj.abc);
</script> -->
</body>
</html>
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 遇到script标签 JS引擎, 解析为js脚本 -->
<!-- 引入 外部脚本,将自动追加到Html之下 -->
<script src="./32.js"></script>
<!-- <script>
console.log('xyz~~~~~~~~~~');
console.log(obj.abc);
</script> -->
</body>
</html>
32.js
javascriptconsole.log('abc');
let obj = {
abc: 1000000
}
console.log('xyz~~~~~~~~~~');
console.log(obj.abc);
这样html, js编写人员就可以分工
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- 遇到script标签 JS引擎, 解析为js脚本 --> <!-- 引入 外部脚本,将自动追加到Html之下 --> <script src="./32.js"></script> <script src="./33.js"></script> </body> </html>
32.js
obj = { abc: 1000000 } console.log(obj.abc);
33.js
console.log(obj); obj = 'aaaaa' console.log(obj);
全局变量污染冲突
2009年js开发, 2015年es6之后,js标准推出包含了模块化。区别于CommonJS(nodejs使用CommonJS).
我们使用es6之后的标准模块化方法。
自动严格模式
import语句,导入另一个模块导出的绑定
visual code中
33.js
/** * ES6定义 * 导出模块A */ class A { constructor(x) { this.x = x } showX() { console.log(this.x); } } const a = new A(3) console.log(a); // A { x: 3 } a.showX() // 3
32.js
import A from './33.js' /** * F8 使用node-exec插件,调用nodejs执行 * * SyntaxError: Cannot use import statement outside a module * 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法; * * 需要把当前源码转换为老的语法 */ console.log(A);
现在我们使用最新的代码, 但是nodejs, 浏览器中不认,需要源代码转换成旧语法,从而适用于更多的浏览器。
tanspiler转译工具,新语法 ES6+转换为旧语法, 可以在nodejs, 浏览器上运行。流行的是babel
http://babeljs.io 点开try it out
新功能 Promise , 老的里面补充上, 需要额外增加, polyfill 或 corejs
https://babeljs.io/docs/en/usage
shell$ node --version
v16.13.0
install -dv devops/src
cd devops/
#初始化
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (devops)
version: (1.0.0)
description: devops mykernel.cn
entry point: (index.js)
test command: test.js
git repository: git@github.com/slcnx/devops.git
keywords: devops mykernel blog
author: slcnx
license: (ISC) MIT
About to write to D:\文档\devops\devops\package.json:
{
"devDependencies": {
"@babel/cli": "^7.17.10",
"@babel/core": "^7.17.10",
"@babel/preset-env": "^7.17.10"
},
"name": "devops",
"version": "1.0.0",
"description": "devops mykernel.cn",
"main": "index.js", # 入口包
"scripts": {
"test": "test.js"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/slcnx/devops.git"
},
"keywords": [
"devops",
"mykernel",
"blog"
],
"author": "slcnx",
"license": "MIT",
"bugs": {
"url": "https://github.com/slcnx/devops/issues"
},
"homepage": "https://github.com/slcnx/devops#readme"
}
Is this OK? (yes) yes
入口包 index.js
测试文件 test.js
在项目根目录 .npmrc
bashregistry=https://registry.npm.taobao.org
shellnpm install --save-dev @babel/core @babel/cli @babel/preset-env
$ ls -l
total 213
drwxr-xr-x 1 21923 197609 0 5月 2 12:49 node_modules/
-rw-r--r-- 1 21923 197609 128 5月 2 12:49 package.json
-rw-r--r-- 1 21923 197609 187063 5月 2 12:49 package-lock.json
drwxr-xr-x 1 21923 197609 0 5月 2 12:48 src/
$ du -sh *
18M node_modules
4.0K package.json
184K package-lock.json
0 src
--save-dev
babel编译js时使用,将新语法转义为老语法,和填坑。编译后生成js文件,可以部署, 这个时候babel就可以不要了。
npm help install
--save
编译后,js中带这些包
在项目根目录,准备文件 babel.config.json
json{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "entry",
// "useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
]
}
详情说明 https://babeljs.io/docs/en/babel-preset-env
usage
使用什么css/依赖的函数/类,就打包什么;
js有版本问题,打包时(webpack包完成)利用babel转换语法,进行折行压缩js, 生成一个js文件。
shell./node_modules/.bin/babel src --out-dir lib
或
npx babel src --out-dir lib
# npx 相当于 npm execute, 即执行$(npm bin)目录下的文件
bash$ ls -l
total 214
-rw-r--r-- 1 21923 197609 272 5月 2 12:58 babel.config.json
drwxr-xr-x 1 21923 197609 0 5月 2 13:08 lib/ # 编译后的脚本
drwxr-xr-x 1 21923 197609 0 5月 2 13:03 node_modules/
-rw-r--r-- 1 21923 197609 598 5月 2 13:03 package.json
-rw-r--r-- 1 21923 197609 187159 5月 2 13:03 package-lock.json
drwxr-xr-x 1 21923 197609 0 5月 2 12:48 src/ # 编译源脚本
执行$(npm bin)目录下的文件,另一种方法 编辑 package.json
json"scripts": { "test": "test.js", "builder": "babel src --out-dir lib" },
调用
shell$ npm run builder > devops@1.0.0 builder # 名@版本 命令名 > babel src --out-dir lib # 命令值 Successfully compiled 2 files with Babel (1265ms).
在src/目录下放模块化语
src/33.js
shell/** * ES6定义 * 导出模块A */ class A { constructor(x) { this.x = x } showX() { console.log(this.x); } } const a = new A(3) console.log(a); // A { x: 3 } a.showX() // 3
src/32.js
shellimport A from './33.js' /** * F8 使用node-exec插件,调用nodejs执行 * * SyntaxError: Cannot use import statement outside a module * 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法; * * 需要把当前源码转换为老的语法 */ console.log(A);
shell$ npx babel src --out-dir lib
Successfully compiled 2 files with Babel (1122ms).
# 现在可以导入了
$ node lib/32.js
A { x: 3 }
3
{} # 不对
使用官方的语法导出
src/33.js
diff/**
* ES6定义
* 导出模块A
*/
+export class A {
constructor(x) {
this.x = x
}
showX() {
console.log(this.x);
}
}
const a = new A(3)
console.log(a); // A { x: 3 }
a.showX() // 3
shell$ npx babel src --out-dir lib
Successfully compiled 2 files with Babel (1128ms).
21923@slc-pc-home MINGW64 /d/文档/devops/devops
$ node lib/32.js
A { x: 3 }
3
undefined # 现在导出是对缺省语法
src/33.js
diff/**
* ES6定义
* 导出模块A
*/
+export default class A {
constructor(x) {
this.x = x
}
showX() {
console.log(this.x);
}
}
const a = new A(3)
console.log(a); // A { x: 3 }
a.showX() // 3
shell$ npx babel src --out-dir lib
Successfully compiled 2 files with Babel (1148ms).
21923@slc-pc-home MINGW64 /d/文档/devops/devops
$ node lib/32.js
A { x: 3 }
3
[class A] # 现在拿到 A类了
$ node src/32.js
(node:18172) Warning: To load an ES module, set "type": "module" in the package.
json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
D:\文档\devops\devops\src\32.js:1
import A from './33.js'
^^^^^^
nodejs,只能执行转换后的js, 对ES6语法导入导出不支持。
缺省只能有一个, 导入 import A
非缺省可以多个, 导入 import {b}
src/33.js
/** * ES6定义 * 导出模块A */ export default class A { constructor(x) { this.x = x } showX() { console.log(this.x); } } const a = new A(3) console.log(a); // A { x: 3 } a.showX() // 3
src/32.js
import A from './33.js' /** * F8 使用node-exec插件,调用nodejs执行 * * SyntaxError: Cannot use import statement outside a module * 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法; * * 需要把当前源码转换为老的语法 */ console.log(A);
$ npx babel src --out-dir lib && node lib/32.js Successfully compiled 2 files with Babel (1201ms). A { x: 3 } 3 [class A]
src/33.js
/** * ES6定义 * 导出模块A */ export default class A { constructor(x) { this.x = x } showX() { console.log(this.x); } } const a = new A(3) console.log(a); // A { x: 3 } a.showX() // 3 export const b = 100;
src/32.js
import A, { b } from './33.js' /** * F8 使用node-exec插件,调用nodejs执行 * * SyntaxError: Cannot use import statement outside a module * 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法; * * 需要把当前源码转换为老的语法 */ console.log(A); console.log(b, '~'.repeat(12));
$ npx babel src --out-dir lib && node lib/32.js Successfully compiled 2 files with Babel (1374ms). A { x: 3 } 3 [class A] 100 ~~~~~~~~~~~~
src/33.js
javascript/**
* ES6定义
* 导出模块A
*/
export default class A {
constructor(x) {
this.x = x
}
showX() {
console.log(this.x);
}
}
const a = new A(3)
console.log(a); // A { x: 3 }
a.showX() // 3
const b = 100;
let c = 300
var d = 200
export { b, d }
export function test(a, b) {
return a + b
}
src/32.js
javascriptimport A, { b, d, c, test } from './33.js'
/**
* F8 使用node-exec插件,调用nodejs执行
*
* SyntaxError: Cannot use import statement outside a module
* 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法;
*
* 需要把当前源码转换为老的语法
*/
console.log(A);
console.log(b, d, '~'.repeat(12));
console.log(c); // 未导出
console.log(test(100, 300));
shell$ npx babel src --out-dir lib && node lib/32.js
Successfully compiled 2 files with Babel (1350ms).
A { x: 3 }
3
[class A]
100 200 ~~~~~~~~~~~~
undefined
400
32.js
import A, { b, d as D, c } from './33.js' /** * F8 使用node-exec插件,调用nodejs执行 * * SyntaxError: Cannot use import statement outside a module * 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法; * * 需要把当前源码转换为老的语法 */ console.log(A); console.log(b, D, '~'.repeat(12)); console.log(c); // 未导出
32.js
javascriptimport Clz, { b, d as D, c } from './33.js'
/**
* F8 使用node-exec插件,调用nodejs执行
*
* SyntaxError: Cannot use import statement outside a module
* 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法;
*
* 需要把当前源码转换为老的语法
*/
console.log(Clz);
console.log(new Clz(158).x);
console.log(b, D, '~'.repeat(12));
console.log(c); // 未导出
缺省导入,任意名即可
shell$ npx babel src --out-dir lib && node lib/32.js
Successfully compiled 2 files with Babel (1232ms).
A { x: 3 }
3
[class A]
158
100 200 ~~~~~~~~~~~~
undefined
javascript/**
* 方式一
*
* from可以写文件名,可以忽略js后缀
*/
// import A, { b, d, c, test } from './33.js'
// import A, { b, d, c, test } from '33'
/**
* 方式二
* 可以将自定义导入和缺省导入分开导入
*/
import { b, d, c, test } from './33'
import A from './33'
/**
* 方式三
* 可以将所有合并为一个变量
*/
import * as newModule from './33'
console.log(newModule, '~'.repeat(33)); // { b: 100, d: 200, default: [class A], test: [Function: test] } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
console.log(newModule.test(1, 3)); // 4
/**
* F8 使用node-exec插件,调用nodejs执行
*
* SyntaxError: Cannot use import statement outside a module
* 不支持导入,nodejs内部使用的CommonJS方法导入,导出;需要最新的ES6语法;
*
* 需要把当前源码转换为老的语法
*/
console.log(A);
console.log(b, d, '~'.repeat(12));
console.log(c); // 未导出
console.log(test(100, 300));
ES6开始支持
js解释器是单线程t1执行的,网络请求会卡住。应该使用异步, 安排回调,做完自动做回调函数。
异步,就把这个函数放在另一个线程t2,处理完成之后,把数据放队列 。
t1会一直看着这个队列, 队列有数据了,就处理队列。
node直接支持,不需要转义
javascript/**
* Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作;
* Promise有三种状态
* 1)pending 还未处理完,即正在处理。
* 2)成功没有显示状态,fullfilled
*
setTimeout 过几s才执行
setInterval 每几s执行
*/
let p1 = new Promise(
// executor
/**
* 谁先执行谁有用
* @param {*} resolve 解决
* @param {*} reject 未解决
*/
(resolve, reject) => {
// 答应你干的事
setTimeout(() => {
// 换成功和失败的顺序
/**
*
* reject('failed') // rejected 在上
结果:
Promise { <pending> }
Promise { <pending> }
+++++++++++++++++++++++++++++++++
failed +++++++++++++++++++++++++++++++++
failed >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Promise { <rejected> 'failed' }
*
resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果
reject('failed') // rejected
结果:
Promise { <pending> }
Promise { <pending> }
+++++++++++++++++++++++++++++++++
{ a: 1, b: 2 } #################################
Promise { { a: 1, b: 2 } }
Promise { { a: 1, b: 2 } }
*
*/
resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果
reject('failed') // rejected
console.log('+'.repeat(33));
}, 3000)
}
)
/**
* Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象;
* Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象;
*
p2.then().catch().then() promise链,可以逐级处理
*/
// let p2 = p1.then()
// let p3 = p1.catch()
let p2 = p1.then(
value => { console.log(value, '#'.repeat(33)); }, // Promise 中先 调用了resolve; 成功调用
reason => { console.log(reason, '+'.repeat(33)); } // Promise 中先 调用了reject; 失败回调
)
let p3 = p1.catch(reason => { console.log(reason, '>'.repeat(33)); })
/**
* 看线程是否做完, 可以循环看线程的状态
* 每2s调用函数
* F9 可以取消node执行
*
Promise { <pending> }
Promise { <pending> }
Promise { 'ok' }
Promise { 'ok' }
Promise { 'ok' }
*/
setInterval(() => {
console.log(p1);
}, 1000)
Promise { '123' }
, 失败就Promise { <rejected> 'failed' }
javascript/**
* Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作;
* Promise有三种状态
* 1)pending 还未处理完,即正在处理。
* 2)成功没有显示状态,fullfilled
*
setTimeout 过几s才执行
setInterval 每几s执行
*/
let p1 = new Promise(
// executor
/**
* 谁先执行谁有用
* @param {*} resolve 解决
* @param {*} reject 未解决
*/
(resolve, reject) => {
// 答应你干的事
setTimeout(() => {
reject('failed') // rejected
resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果
console.log('+'.repeat(33));
}, 3000)
}
)
/**
* Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象;
* Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象;
*
p2.then().catch().then() promise链,可以逐级处理
*/
let p2 = p1.then() // 不给实参,相当于两个形参,是2个undefined
let p3 = p1.catch()
/**
* 看线程是否做完, 可以循环看线程的状态
* 每2s调用函数
* F9 可以取消node执行
*
*/
setInterval(() => {
console.log(p1, p2);
console.log(p1==p2, p1===p2);
}, 1000)
javascript/**
* Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作;
* Promise有三种状态
* 1)pending 还未处理完,即正在处理。
* 2)成功没有显示状态,fullfilled
*
setTimeout 过几s才执行
setInterval 每几s执行
*/
let p1 = new Promise(
// executor
/**
* 谁先执行谁有用
* @param {*} resolve 解决
* @param {*} reject 未解决
*/
(resolve, reject) => {
// 答应你干的事
setTimeout(() => {
resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果
reject('failed') // rejected
console.log('+'.repeat(33));
}, 3000)
}
)
/**
* Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象;
* Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象;
*
p2.then().catch().then() promise链,可以逐级处理
*/
/**
* p2 就是undefined了
+++++++++++++++++++++++++++++++++
{ a: 1, b: 2 } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Promise { { a: 1, b: 2 } } Promise { undefined }
false false
Promise { { a: 1, b: 2 } } Promise { undefined }
...
*/
let p2 = p1.then(
value => {
console.log(value, '~'.repeat(33))
// return value // 返回值就是p2实例的成功原因
}
) // 不给实参,相当于两个形参,是2个undefined
let p3 = p1.catch()
/**
* 看线程是否做完, 可以循环看线程的状态
* 每2s调用函数
* F9 可以取消node执行
*
*/
setInterval(() => {
console.log(p1, p2);
console.log(p1==p2, p1===p2);
}, 1000)
/** * Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作; * Promise有三种状态 * 1)pending 还未处理完,即正在处理。 * 2)成功没有显示状态,fullfilled * setTimeout 过几s才执行 setInterval 每几s执行 */ let p1 = new Promise( // executor /** * 谁先执行谁有用 * @param {*} resolve 解决 * @param {*} reject 未解决 */ (resolve, reject) => { // 答应你干的事 setTimeout(() => { reject('failed') // rejected resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果 console.log('+'.repeat(33)); }, 3000) } ) /** * Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象; * Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象; * p2.then().catch().then() promise链,可以逐级处理 */ /** * p2 就是undefined了 Promise { <pending> } Promise { <pending> } false false Promise { <pending> } Promise { <pending> } false false +++++++++++++++++++++++++++++++++ failed +++++++++++++++++++++++++++++++++ failed > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Promise { <rejected> 'failed' } Promise { undefined } false false Promise { <rejected> 'failed' } Promise { undefined } false false */ let p2 = p1.then(undefined,reason => { console.log(reason, '+'.repeat(33)); return reason } ) // 不给实参,相当于两个形参,是2个undefined let p3 = p1.catch(reason => { console.log(reason, '> '.repeat(33)); return '123' }) /** * 看线程是否做完, 可以循环看线程的状态 * 每2s调用函数 * F9 可以取消node执行 * */ setInterval(() => { console.log(p1, p2); }, 1000)
由于promise,调用后then/catch均返回promise.
如果成功,所有then -> value 语句均会执行。
如果失败,走then -> reason语句 或 catch语句,默认转成功,一旦显式定义Promise.reject才继续走失败。
/** * Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作; * Promise有三种状态 * 1)pending 还未处理完,即正在处理。 * 2)成功没有显示状态,fullfilled * setTimeout 过几s才执行 setInterval 每几s执行 */ let p1 = new Promise( // executor /** * 谁先执行谁有用 * @param {*} resolve 解决 * @param {*} reject 未解决 */ (resolve, reject) => { // 答应你干的事 setTimeout(() => { reject('failed') // rejected resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果 console.log('++++++++++++++ Promise+++++++++++++++++++'); }, 3000) } ) /** * Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象; * Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象; * p2.then().catch().then() promise链,可以逐级处理 */ // p1成功, then成功, p2显示then的成功的结果;undefined // p1成功, let p2 = p1.then(value => { console.log('++++++++++++++ p1 then +++++++++++++++++++'); return value },reason => { console.log('++++++++++++++ p1 reason +++++++++++++++++++'); return Promise.reject(reason) } ) // 不给实参,相当于两个形参,是2个undefined p2.then(value => { console.log('++++++++++++++ p2 then +++++++++++++++++++'); return value },reason => { console.log('++++++++++++++ p2 reason +++++++++++++++++++'); return Promise.reject(reason) } ) // 不给实参,相当于两个形参,是2个undefined let p3 = p1.catch(reason => { console.log('++++++++++++++ p3 catch +++++++++++++++++++'); return '123' }) p3.then(value => { console.log('++++++++++++++ p3 then +++++++++++++++++++'); // return value },reason => { console.log('++++++++++++++ p3 reason +++++++++++++++++++'); return Promise.reject(reason) } ) let p4 = p2.catch(reason => { console.log('++++++++++++++ p4 catch +++++++++++++++++++'); return '123' }) p4.then(value => { console.log('++++++++++++++ p4 then +++++++++++++++++++'); // return value },reason => { console.log('++++++++++++++ p4 reason +++++++++++++++++++'); return Promise.reject(reason) } ) /** * 看线程是否做完, 可以循环看线程的状态 * 每2s调用函数 * F9 可以取消node执行 * */ setInterval(() => { console.log(p1,p2,p3,p4); }, 1000)
javascript/**
* Promise 完成异步的事, 答应你干的事,会自动开新线程; 主线程继续工作;
* Promise有三种状态
* 1)pending 还未处理完,即正在处理。
* 2)成功没有显示状态,fullfilled
*
setTimeout 过几s才执行
setInterval 每几s执行
*/
let p1 = new Promise(
// executor
/**
* 谁先执行谁有用
* @param {*} resolve 解决
* @param {*} reject 未解决
*/
(resolve, reject) => {
// 答应你干的事
setTimeout(() => {
resolve({ a: 1, b: 2 }) // fulfilled 完成了; 里面是成功的结果
reject('failed') // rejected
console.log('++++++++++++++ Promise+++++++++++++++++++');
}, 3000)
}
)
/**
* Promise().then() p1返回处理,2个参数必须是单参函数。处理成功和失败; 返回1个新的promise对象;
* Promise().catch() 1个单参函数, 只能处理异常; 返回1个新的promise对象;
*
p2.then().catch().then() promise链,可以逐级处理
*/
// Promise 对象是awaitable对象
async function test() {
// let ret = p1.then(value = console.log(value);)
let value = await p1 // await从then->value函数中获取value,返回。await暂停函数执行
console.log(value);
}
console.log('test start ');
test()
console.log('test stop');
console.log('~~~~~~~~~~~~~');
本文作者:mykernel
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!