基础概念
OOP FP 异步编程 事件循环模型 闭包 MVX 后端编程模型 自动化检查 测试 编译 打包 前后端分离实践
JS语法上不可封装,但技巧上可以封装,使用闭包,Symbol封装。
ES标准
语言定位为:函数式编程的、面向对象的、动态的、事件驱动的、脚本语言(宿主)
Html5 最大特性,对JS开放了硬件接口。
ES数据类型
number boolean string null undefined 基本数据类型,null为对象。
Symbol
Object
只要带原型proto就是对象,唯一特殊的是null没有原型。除基本类型(除null外)都是对象。
判断对象为null,typeof()
ES6才出现的class,也是假的。
API的分布
- 全局挂载一部分
- 内置函数、对象,两种
- 宿主环境上
- 第三方库
let People=(function () {
var breath=Symbol('breath')
class Animal{
constructor(){
this.age=0;
}
walk(){
this[breath]()
console.log("walk...")
}
[breath](){
console.log("breath")
}
}
class Humanextends Animal{
}
return Human
})()
let a=new People()
a.walk()
字面量
123,true, "ddd",'dfss',asdklalds
ksdfa ladal
let as = [1,2,3]
let obj = {id:1, "my-name":'john', sex:true, fav: ['basket'],"my-friend":{....}}
/a+/ig
new RegExp('a+','ig')
对象操作方法
o = new Object()
Object.preventExtensions(o)
/*如果一个对象可以添加新的属性,则这个对象是可扩展的。`Object.preventExtensions()`将对象标记为不再可扩展,因此它将永远不会具有超出它被标记为不可扩展的属性。注意,一般来说,不可扩展对象的属性可能仍然可被删除。尝试将新属性添加到不可扩展对象将静默失败或抛出[`TypeError`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError "TypeError(类型错误) 对象用来表示值的类型非预期类型时发生的错误。")(最常见但不排除其他情况,如在[strict mode](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode "此页面仍未被本地化, 期待您的翻译!")中)。
`Object.preventExtensions()`仅阻止添加自身的属性。但属性仍然可以添加到对象原型。
一旦使其不可扩展,就无法再对象进行扩展。
*/
Object.seal(o)
/*
通常,一个对象是[可扩展的](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible "Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。")(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出[`TypeError`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError "TypeError(类型错误) 对象用来表示值的类型非预期类型时发生的错误。")(在[严格模式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode "如果你想改变你的代码,让其工作在具有限制性JavaScript环境中,请参阅转换成严格模式。") 中最常见的,但不唯一)。不会影响从原型链上继承的属性。
*/
Object.freeze(o)
/*被冻结对象自身的所有属性都不可能以任何方式被修改。任何修改尝试都会失败,无论是静默地还是通过抛出[`TypeError`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError "TypeError(类型错误) 对象用来表示值的类型非预期类型时发生的错误。")异常(最常见但不仅限于[strict mode](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode "如果你想改变你的代码,让其工作在具有限制性JavaScript环境中,请参阅转换成严格模式。"))。
数据属性的值不可更改,访问器属性(有getter和setter)也同样(但由于是函数调用,给人的错觉是还是可以修改这个属性)。如果一个属性的值是个对象,则这个对象中的属性是可以修改的,除非它也是个冻结对象。数组作为一种对象,被冻结,其元素不能被修改。没有数组元素可以被添加或移除。
这个方法返回传递的对象,而不是创建一个被冻结的副本。
*/
数组的x函数
常用操作
push pop unshift shift slice splice sort reverse
高阶函数
forEach() findIndex() filter() map() reduce every() some()
let as=[3,2,4,9,4,]
as.push(8)
console.log(as)
as.pop()
console.log(as)
as.unshift(6)
console.log(as)
as.shift()
console.log(as)
let rs = as.slice(1,3)
console.log(rs)
as.splice(1,3,11, 34,45)
console.log(as)
let index = as.indexOf(3)
console.log(index)
let rs1=as.map((item, inx)=>inx%2?item*2:item)
console.log(rs1)
let rs2=as.filter(item=>item>5)
console.log(rs2)
console.log(as)
rs1 = as.reduce((pre,cur)=>pre + cur,10)
console.log(rs1)
rs1 = as.every(item=>item>5)
console.log(rs1)
rs1 = as.some(item=>item>5)
console.log(rs1)
函数
Fuction is algorithm
Fuction is object(is Data)
Fuction is Class(is Contuctor)
Fuction is closure(is program)
函数没有重载概念,因为其也是一个对象,只能根据名字区分,无法根据参数进行区分 。
偏函数 返回的函数
高阶函数 作为参数的函数
闭包
一个函数或对象里面维护了一个局部变量,叫闭包
定义:可以访问外界,但其内部对外界不可见的函数。
function functionFactory(init){
let x=0;
function sum(a,b){
return a+b+init
}
return sum;
}
let ss = functionFactory(10)
let ss1 = functionFactory(20)
console.log(ss(2,3))
console.log(ss1(2,3))
console.log("=".repeat(20))
function counterFactory(){
let value=0
return function(){
return ++value;
}
}
let c1=counterFactory()
for (let i = 0; i <10; i++) {
console.log(c1())
}
原生 JS 的MV* 模式完成的前端Demo
HTML的部分
···
MVVM With raw javascript
ID | 图书名称 | 图书价格 | 图书数量 | 删除 |
---|
价格总计:
···
JavaScript部分
···
window.onload=function () {
//项目的数据模型
let books=[]
let app=document.querySelector('#app')
let url="http://localhost:3000/books"
/**
* 完成数据绑定、事件绑定
*/
function render(){
let tbody=app.querySelector("#books-list>tbody");
tbody.innerHTML="";
books.forEach(book=>{
let tr=document.createElement("tr")
tr.appendChild(document.createElement("td")).innerHTML=book.id+"";
tr.appendChild(document.createElement("td")).innerHTML=book.name+"";
tr.appendChild(document.createElement("td")).innerHTML=book.price+"";
tr.appendChild(document.createElement("td")).innerHTML=book.count+"";
let btn=document.createElement('button');
btn.innerText="删除"
btn.addEventListener("click",()=>deleteBook(book))//事件绑定
tr.appendChild(document.createElement("td")).appendChild(btn)
tbody.appendChild(tr);
})
app.querySelector('#books-list+h3>span').innerHTML=total()+""
}
/**
* 向模型中添加数据
*/
function addBook() {
//采集表单数据
let addBookForm=app.querySelector('#add-book-form')
let name=addBookForm.querySelector('[name=name]').value.trim();
let price=parseFloat(addBookForm.querySelector('[name=price]').value.trim())
let count=parseInt(addBookForm.querySelector('[name=count]').value.trim())
let book={name:name,price:price,count:count};
//ajax请求
fetch(url,{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify(book)
})
.then(res=>res.json())
.then(nb=>{
books.push(nb)
render()
})
}
//被绑定的事件,完成从模型中删除数据
function deleteBook(book) {
fetch(url+"/"+book.id,{
method:"DELETE"
}).then(rs=>{
let index=books.indexOf(book);
books.splice(index,1);
render();
})
}
//总价计算函数
function total(){
return books.reduce(function (prev,cur) {
return prev+cur.price*cur.count;
},0)
}
//立即执行函数,完成初始化的全部工作
(function(){
//异步初始化数据,并调用render完成绑定工作
fetch(url,{
method:'GET',
})
.then(res=>res.json())
.then(bks=>{
books=bks
render()
})
app.querySelector('#add-book-form')
.addEventListener('submit',function (event) {
addBook();
event.preventDefault();
})
})();
}
···
this指针
this 是在调用时被传入的指针
当作函数直接调用时,它是global对象;当作方法调用时,它是对象本身。
当事件回调时,是事件源本身。
事件回调时,回调函数如果使用Function定义时,this是事件源本身。如果是使用=>定义的,则this是定义的地方的对象。
fn(argv1,argv2)
fn.apply(this,[argv1,argv2])
fn.call(this, argv1,argv2)s
//这样fn的this被绑定到这个this上,也就是=>函数定义函数的真实定义。
let fn1=fn.bind(this)