代码调试方式:直接在html文件中插入debugger;
代码行
var a = 1+3
程序的执行单位为行(line),
var a = 1+3; var b = 'abc'
:var a=1+3
:var a = 1+3;
;;; //3个空语句
typeof undefined
// undefined
[object Number] // 数值
[object String] // 字符串
[object Boolean] // 布尔值
[object undefined] //
[object Null] //
[object Arguments] // arguments对象
[object Function] //
[object Error] //
[object Date] //
[object RegExp] //
// 看到一个值到底能分什么类型
Object.prototype.toString.call(2) //
Object.prototype.toString.call('') //
Object.prototype.toString.call(true)
Object.prototype.toString.call(undefined)
// 在此基础上,专门判断某种类型数据的方法;写一个比typeof
var type = function(o) {
var s = Object.prototype.toString.call(o);
return s.match(/\[object(.*?)\]/)[1].toLowerCase();
}
['Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp'].forEach(function(t) {
type['is' + t] = function(o) {
return type(o) === t.toLowerCase();
}
});
type.isObject({}) // true
type.isNumber(NaN)
type.isRegExp(/abc/)
Object.prototype.toLocaleString()// 方法与toString的返回结果
var obj = {};
obj.toString(obj) //"[object object]"
obj.toLocaleString(obj) // "[object object]"
var obj = {} //
obj.toString() // '[object object]',其中第二个Object表示该值的构造函数
// 由于实例对象会自定义toString方法,覆盖Object.prototype.toString,
obj.toLocaleString(obj)
// 方法的主要作用是留一个接口,让不同对象实现自己版本的toLocaleString
var person = {
toString: function() {
return 'Henry Norman Bethune';
}
toLocaleString: function() {
return '白求恩';
}
}
person.toString()
person.toLocaleString()
{
}
typeof
运算符:typeof 123 // number
typeof ''
instanceof
运算符:Object.prototype.toString
方法:TypeScript 是JavaScript 的超集(ts是微软开发的开源编程语言),即包含JavaScript 的所有元素,能运行JavaScript 的代码,并扩展了JavaScript 的语法
1)TypeScript 引入了 JavaScript(初始)没有的“类”概念
2)TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块中。
3)js没有重载概念,ts有可以重载
4)ts增加了接口interface、泛型、类、类的多态、继承等
5)ts对比js基础类型上,增加了 void/never/any/元组/枚举/以及一些高级类型
6)js有的类型:undefined、boolean类型、number类型、string类型、object(array类型、null),js是动态类型、变量能随时更改
var a = 1; a = 'hello';
/**
* 重新声明已存在的变量无效
* */
var x = 1;
var x; // 无效
x//1
/**
* 赋值会覆盖
*/
var x = 2;
x //2
ts新增的类型:tuple类型(元组类型)、enum类型(枚举类型)、any类型(任意类型)
a)Symbol类型:
Symbol是JS中一种新的基本数据类型,引自ES6标准。是不可变且唯一的数据类型,能创建独一无二的键(key),其描述符相同也不相等
① 遍历带有Symbol
的对象,结果Symbol没有出现在遍历结果中
const obj = {
a: 'a',
b: 'b',
c: 'c',
[Symbol('a')]: '我是symbol'
}
for (let key in obj) {
cosole.log('obj.' + key + '=我是' + obj[key])
}
// 直接定义新属性或修改现有,语法规则obj, prop, descriptor
// obj目标对象,prop属性名称,descriptor描述符
Object.defineProperty(obj,
'enumerableTrue', {
value: 42,
writable: false
}
)
//
var obj = Object.defineProperties({}, {
p1: {value: 1, enumerable: true},
p2: {}
})
② Symbol主要用于对象属性的唯一标识。对象中Symbol作为属性名,定义
③ 字符串String的声明方式var str = ‘str’,Symbol声明类似,调用构造函数Symbol()
const mySymbol = Symbol() // 创建Symbol
// 使用Symbol作为对象属性名
const obj = {}
const mySymbol = Symbol()
obj[mySymbol] = 'Symbol属性'
console.log(obj[mySymbol]) // 输出
// 描述符
const mySymbol = Symbol('描述符')
console.log(mySymbol.toString()) // 输出
// 内置属性
const mySymbol = Symbol.iterator
const arr = [1, 2, 3]
const iterator = arr[mySymbol]()
console.log(iterator.next()) // 输出:{value:1, done:false}
// 这是张三的代码
(function(){
let a = 10
console.log(a)
})()
// 这是李四的代码
let sayBye = new Function('console.log("bye bye!!")')
sayBye()
// 函数的不定参(可变参)使用
② ES5对象属性名均为字符串,易造成属性名的冲突。若使用他人提供的对象,但想为这个对象添加新方法(mixin模式)
Symbol函数不能使用new命令,
③ Symbol的使用场景
const name = Symbol('name')
const age = Symbol('age')
const person = {
[name]: 'John',
[age]: 30
}
④ 内置属性
const mySymbol = Symbol.iterator
const arr = [1,2,3]
const iterator = arr[mySymbol]()
console.log(iterator.next()) // 输出: {value:1, done:false}
④ 使用Symbol具以下优势
a. 属性名的唯一性:防止属性被意外访问
b. 防止属性被意外访问:避免属性名冲突问题。多个Symbol值使用相同描述符,依然不同属性名
c. 扩展对象的功能:通过自定义Symbol,能为对象添加自定义行为,如迭代器、比较器等;因此能更灵活地扩展对象,使其具备特定行为
d. 安全性提升:Symbol属性不被常规的属性遍历方法访问,能在一定程度上提升安全性,防止属性被意外修改
⑤ 使用Symbol的缺点
a. 无法遍历:Symbol属性名,无法通过常规的属性遍历方法(如for…in)获取,若要遍历,则不能使用Symbol作为属性名
b. 内存泄漏:因Symbol创建的属性唯一,一旦创建后无法被销毁或垃圾回收机制回收。若大量使用Symbol创建,会造成内存泄漏的问题
c. 可调试性差:Symbol属性值在控制台输出时,没有明确标识,不易调试和查看对象的具体属性
d. 不可序列化:Symbol值不能被JSON.stringify()序列化,也不能传给其他线程或进程
undefined
, null
, boolean
, number
, string
;
true>false
:Object
, Array
, Function
, Data
)Number()
: e.g., Number(‘123’)parseInt()
:e.g., parseInt(‘12.3px’)输出12,而parseFloat(‘12.95px’)输出12.95// 案例:将秒数转为时间
let secondNum
h = parseInt(sccondNum/(60*60)%24) // 避免超过24小时
m = parseInt(sccondNum/60%60) // 避免超过1小时
s = parseInt(sccondNum%60)
h = h<10? '0'+h : h
m = h<10? '0'+m : m
s = s<10? '0'+s : s
console.log(h,':',m,':',s)
parseFloat()
typeof(typeof(undefined)) -> "string"
typeof alert === 'object'
在IE6,7,8中,宿主对象是对象而非函数typeof /[0-9]/ == 'function'
typeof /[0-9]/ == 'function'
typeof(null) -> "object"
typeof([]) -> "object"
"[object Xxx]"
的字符串// 不靠谱
function isJSON(str){
if(typeof(str) == "object"){
try{
JSON.parse(str)
return true
}
catch(err){
console.log(err)
return false
}
}
} // 有JSON.parse('123')('{}')('"foo"')等很多例外
// 靠谱
function isJSON_Correct(str){
if(typeof(str) == "object"){
try{
let obj = JSON.parse(str)
if(typeof(obj) == "object" && obj){
return true
} else {
return false
}
}catch(err){
console.log('error:'+str+'!'+err)
return false
}
}
console.log('not a string')
}
// 输出到HTML文档
document.write('嘿嘿') //或其他DOM语句
// e.g., 输出到HTML表格
let age = 19
document.write('
<table>
<tr>
<th>猜猜你多大?</th>
</tr>
<tr>
<td>${age}</td>
</tr>
</table>
')
// 控制台打印输出
console.log('控制台输出成功')
// 输入语句1-弹窗
// 核心-实现成功:prompt('看到了吗')
let zero = prompt('来个字符')
let a = +prompt('来个数字') //prompt前加+能把变量转化为数字型
// 数字嵌入字符串
let age = 200
document.write('我今年${age}岁了')
arr[0]
let arr = [1,2,3,4,5,6]
let length = 0
let elem
// 增加
length = arr.push() // 加到末尾,返回长度
length = arr.unshift() // 加到开头,返回长度
// 删除
elem = arr.pop() // 删除末尾,返回删除元素
elem = arr.shift() // 删除开头,返回删除元素
arr.splice(0,1) // 删除指定元素/个数,()中是左属性是操作开始的下标、右属性是删除的个数
arr.splice(0, arr.length, ...(arrB)) // 删除再拼接arrB
arr.slice(0,1) // splice会修改原数组arr,而slice不会
// 修改,查询:arr[idx]
/// 1. 普通函数
// 声明
function func1(){
// 返回多值-通过数组存储
return [value1,value2]
}
// 执行
let arr = func1()
/// 2. 匿名函数:通过将匿名函数赋值给一个变量来调用,称为函数表达式
// 声明
let fn = function(){
}
// 执行
fn()
/// 3. 立即执行函数
// 方法1
(function(形参{函数体}))(实参)
// 方法2
(function(形参{函数体})(实参))
int getMax (int i1, int i2, int i3=100) {
if (i1<i2) {
i1 = i2
}
return i1>i3 ? i1 : i3
}
#include <stdio.h>
typedef void (*FN_NOTIFY)(const char *pszMsg)
void Notify1()
iRand = int(rand())
if(iRand%9==0) {
sprintf(szBuf, "%d", iRand)
pFn(szBuf)
}
int main() {
FN_NOTIFY pFn;
pFn = Notify1;
Process(pFn);
pFn = Notify2;
Process(pFn);
return 0;
}
// Attention: 0-9的数字补0,使用三元表达式
let num = prompt('数字:')
num = num < 10 ? 0+num : num // 隐式转换
console.log('结果:'+num)
// 1)对象字面量
var obj1 = {
name: "Jack",
age: 26
}
// 2)Object构造函数
var obj2 = new Object()
obj2.name = "Jack"
obj2.age = 26
// 3)构造函数
function Test(name, age){
this.name = name
this.age = age
this.say = function(){
console.log('我能说话')
}
}
var obj3 = new Test('Jack', 26)
var obj4 = new Test('Rose', 25)
2)自定义对象
// 模板
let obj = {
key:value,
method:function
}
// 例子
let per = {
uname:'Tony',
age: 18,
sayHi: function (形参){
document.write('Hi~')
}
}
// 访问属性
// 对象.属性名
person.age
// 对象['属性名']
person['age']
// 访问方法
// 对象.方法名
person.sayHi()
// 修改属性
person.age=17
// 新增属性
person.score=98
// 删除属性
delete person.score
// 用for in循环语句可遍历对象属性:0,1,..不可存取
// 跳过不可遍历的属性。会遍历继承属性
for(let k in person) {
console.log(k)
// toString属性
}
// 2.
Object.defineProperty(obj, 'enumerableTrue', {
value: 'enumerableTrue',
enumerableTrue: true
})
// 3.
Object.defineProperty(obj, 'enumerableTrue', {
value: 'not-enumerableTrue',
enumerableTrue: false
})
//
for(let key in obj) {
console.log()
}
3)内置对象
JavaScript提供的对象,包含各种属性和方法给开发调用
如document.write()、consolo.log()都属于内置对象
/// Math对象
// 1. 随机数random:随机生成一个大于等于0并且小于1的浮点数
Math.random()
// 1.1 产生1-10的随机数
let rand1 = Math.floor(Math.random() * 10 + 1) // 注意范围和下限
// 1.2 不相邻整数中取一个随机数,如2和4中选
let rand2 = Math.random() < 0.5? 2 : 4
// 1.3 不相邻的多整数中产生一个随机数:结合函数参数数组
function selectFromMess(){
return arguments[Math.floor(Math.random()*arguments.length)]
}
let rand3 = selectFromMess(1,6,8)
let box = document.querySelector('#box')
// 2. 向上取整ceil
Math.ceil(num) // 如Math.ceil(-11.2)=-11
// 3. 向下取整floor
Math.floor(num) // 如Math.ceil(11.2)=11
// 4. 最大数max
Math.max(1,2,3)
// 5. 最小数min
Math.min(1,2,3)
// 6. 幂运算pow
Math.pow(x, a) // 球x的a次幂
// 7. 绝对值abs
Math.abs(num)
// 8. 四舍五入取整
Math.round(num) // 先加0.5再向下取整,如Math.round(-11.6)=-12,Math.round(-11.5)=-11
// 9. 三角函数
Math.sin()
Math.cos()
// 10. 平方根
Math.sqrt(num) // num是数字或者可以通过隐式转换来的(如字符串类型)
// 11. eval()函数
// 11.1
即使严格模式下,eval可以读写作用域的变量
(function f(){
})
// 11.2 eval的别名调用:不利于引擎优化执行速度。更麻烦的是,引擎在静态分析的阶段,分辨执行的是eval
var m = eval; // m:eval别名
m('var x = 1');
x // 1
// 为了保证eval的别名不影响代码优化,其内全是全部作用域
var a = 1;
function f() {
var a = 2;
var e;
}
eval.call(null, '...') // eval别名调用形式五花八门
// eval别名调用即使函数中,无论是作用域还是全局作用域;如果非直接调用,都属于别名
window.eval('...')
(1, eval)
var arr = ['a', 'b', 'c]
arr[0] = 'a';
arr[1] = 'b';
var arr [{a:1}, [1,2,3], function(){return true;}]
arr[0] // Object {a:1}
arr[2] // function(){return true;}
// arr数组
var arr = ['a', 'b', 'c'];
['a', 'b', 'c'].length //3
[].length = -1
[].length = Math.pow(2, 32)
[].length = 'abc'
// 数组
var a = [];
a['p'] = 'abc';
a.length
a[2.1] = 'abc';
a.length
// for循环
for(var i=0; i<a.Length; i++) {
console.log(a[i]);
}
// while循环
var i = 0;
colors.forEach(function(color){
console.log(color)
})
var a = [undefined, undefined]
a.forEach(function(x,i) {
console.log(i)
});
Object.keys(a)
var obj = {
}
/// arguments对象:JS没有重载函数(函数/方法名称相同,但参数列表不同)的功能,但arguments能模拟重载;
/// Attention!arguments对象不能显式创建,只有函数开始时才可用
(function(a,b,c){
console.log(arguments) //arguments.length实参个数,arguments.callee引用函数本身-与形参一一映射
console.log(arguments[0]) //支持数组引用
return n + arguments.callee(n-1) // 实现递归
})(1,2,3,4)
//
function max(){
if(){
}
}
//
const arr = [{name: 'wfly'}, {name: 'fnn'}]
for (let key in arr) {
console.log('obj.' + key + '= 我是' + JSON.stringify(arr[key]))
}
let box = document.querySelector('#box')
box.onclick = function() {
console.log('我是匿名函数')
}
box.onclick = null
//
for (let key in testProtoTypeObj) {
console.log('testProtoTypeObj' + key + '=我是' + testProtoTypeObj[key])
}
console.log('====')
//
for (let key in testProtoTypeObj) {
if (testProtoTypeObj.hasOwnProperty(key)) {
console.log('testProtoTypeObj.'+key+'=我是' + testProtoTypeObj[key])
}
}
console.log(testProtoTypeObj) //
&&
(一假则假,因此前假后不执行)和||
(一真则真,因此前真、后不执行)console.log(a)
,找到变量的值、不修改a=2
,找到变量的容器并赋值 ```js
const a = []
export default a
```
导入
```js
// 简写
import a from './a'
// 详细
import {defualt as a} from './a'
```
```js
export const a=[] // 系统会自动转成对象,变成{a:[]}
```
导入
```js
import {a} from './a'
```
```js
const a = []
const b = {}
export {a,b}
```
导入
```js
import {a, b} from '/xxx'
```
```js
export {default as xx} from '/xxx'
```
可以理解为`import xxx from '/xxx` + `export xxx`,先导入再导出
**【应用场景】**:
**step 1. 将本暴露** 如果
**step 2. elseif:**
**step 3. if:**
let copyObj = obj
,copyObj和obj具有相同的地址值。当修改 obj 或 copyObj 任意一个值时都会引起实际对象的值被修改let ele = document.getElementById('"xxx")
let a = new Object() // 此对象的引用计数为1(a引用)
let b = a // 此对象的引用计数为2(a,b引用)
a = null
b = null // 对象的引用次数
... // GC回收此对象
function test() {
let A = new Object() // 此对象的引用计数为1
let B = new Object()
A.b = B
B.a = A
}
test
执行完成后,对象A和B要被清理,但使用引用计数不会被清理,因为引用数量不会为0// COM对象
let ele = document.getElementById("xxx")
let obj = new Object()
// 造成循环引用
obj.ele = ele
ele.obj = obj
// 切断引用关系
obj.ele = null
ele.obj = null
function test(){
let A = new Object()
let B = new Object()
A.b = B
B.a = A
}
// 使用 try-catch 处理同步代码块中的异常
function example1() {
try {
// 可能抛出的异常代码块
const res = func()
} catch (e) {
console.error(e)
} finally { // 在try或catch块结束后都会进入
}
}
// 使用 Promise.catch() 处理异步操作中的异常
function example2() {
somePromiseFunction()
.then(result => {
// 处理 Promise 成功的结果
})
.catch(error => {
console.error(error.message); // 处理 Promise 失败的原因:会在Promise抛出任何错误时执行,并在promise链条上终止
})
}
Promise的基本使用
const myPromise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('foo')
}, 300)
})
myPromise.then((value)=>{
console.log(value,'value')
}).catch((err)=>{
console.log(err)
})
console.log(myPromise, 'myPromise')
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET',url)
xhr.onload=() => resolve(xhr.responseText)
xhr.onerror=() => reject(xhr.statusText)
xhr.send()
})
}
const promise1 = Promise.resolve(3)
const promise2 = 42
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo')
})
const promise4 = Promise.all([1,2,3,Promise.resolve(444)])
Promise.all([promise1, promise2, promise3]).then((val)=>{
console.log(val)
})
async funtion getPrice() {
const [choise, prices] = await
}
Promise.allSettled(promises).then((res) => {
results.forEach((res) => {
console.log(res.status)
})
})
手写Promise
代码如下。
// 4. 定义状态常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 1. 创建MyPromise类
class MyPromise implements Promise {
// 2. 构造函数Constructor,执行
constructor(executor) {
// 13. Promise实现捕获错误
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENDING
// 6. MyPromise定义value和reason,储存执行器成功和失败的返回值
value = null
reason = null
// 9. 实现then方法多次调用添加多个处理函数,初始化回调为数组依次执行
successCallback = []
failCallback = []
// 3. 定义resolve和reject
resolve = value => {
if(this.status !== PENDING) {
return
}
// 改变当前状态
this.status = REJECTED
// 保存返回值
this.reason = reason
// 执行失败回调
while () {
this.failCallback.shift()(this.reason)
}
}
//
reject = reason => {
if(this.status !== PENDING)
return
this.status = REJECTED
}
}
// 2.
function AsyncTask() {
asyncFuncA(function(err, resultA){
if(err) return cb(err);
asyncFuncB(function(err, resultB){
if(err) return cb(err);
asyncFuncC(function(err, resultC){
if(err) return cb(err);
// And so it goes....
})
})
})
}
function AsyncTask(cb) {
asyncFuncA.then(AsyncFuncB)
.then(AsyncFuncC)
.then(AsyncFuncD)
.then(data => cb )
}