function fn(a, c){
console.log(a); //f a(){ }
var a = 123;
console.log(a); //123
console.log(c); //2
function a(){ };
if(false){
var d = 678
}
console.log(d); //undefined
console.log(b); //undefined
var b = function(){};
console.log(b); //f (){}
console.log(c); //2
}
fn(1, 2)
//预编译
//作用域的创建阶段,预编译的阶段
//预编译的时候做了哪些事
//js的变量对象 AO对象 供js引擎自己区访问的
//预编译过程:
/*
1.创建了ao对象
2.找形参和变量的声明 作为对象的属性名 值是undefined
3.实参和形参相统一
4.找函数声明 会覆盖变量的声明
*/
AO:{
a:undefined => 1 => function a(){}
c:undefined => 2 => function c(){}
d:undefined
b:undefined
}
单例
const loginLayer = function () {
let div = document.createElement('div')
div.innerHTML = '我是登录的弹窗'
div.style.display = 'block'
document.body.appendChild(div)
return div
}
const getSingle = function (loginLayer) {
let result
return function(){
return result || (result = loginLayer())
}
}
const fn = getSingle(loginLayer)
document.getElementById('btn').onclick = fn
策略模式:
初版:
const registerForm = document.getElementById('registerForm')
registerForm.onsubmit=function(){
if(registerForm.username.value === ''){
alert("用户名不能为空")
return false
}
if(registerForm.password.value.length<6){
alert('密码长度不能小于6')
return false
}
}
策略模式版:
<body>
<form action="xxx.com" method='post' id=registerForm>
请输入用户名:<input type="text" name="username">
请输入密码:<input type="password" name="password">
<button>提交</button>
</form>
<script>
const registerForm = document.getElementById('registerForm')
const strategies = {
isNonEmpty: function(value, errorMsg){
if(value === ''){
return errorMsg
}
},
isMinLength: function(value,length,errorMsg){
if(value.length<6){
return errorMsg
}
}
}
const Validator = function(){
this.cache = []
}
Validator.prototype.add = function(dom,rule,errorMsg){
const ary = rule.split(':')
this.cache.push(function(){
const strategy = ary.shift()
ary.unshift(dom.value)
ary.push(errorMsg)
return strategies[strategy](...ary)
})
}
Validator.prototype.start = function(){
for(let i = 0,vaFunc;vaFunc = this.cache[i++];){
let msg = vaFunc()
if(msg) {
return msg
}
}}
const validateFun = function(){
const validator = new Validator()
validator.add(registerForm.username, 'isNonEmpty', '用户名不能为空')
validator.add(registerForm.password, 'isMinLength:6', '密码长度不能小于6')
const errorMsg = validator.start()
return errorMsg
}
registerForm.onsubmit = function(){
const errorMsg = validateFun()
if(errorMsg){
alert(errorMsg)
return false
}
}
</script>
</body>
发布订阅模式
const shopObj = {}
shopObj.list = []
shopObj.listen = function(key, fn){
if(!this.list[key]){
this.list[key] = []
}
this.list[key].push(fn)
}
shopObj.trigger = function(){
const key = Array.prototype.shift.call(arguments)
let fn
let fns = this.list[key]
if(!fns || fns.length ===0 ){
return
}
for(let i = 0;fn = fns[i];i++){
fn(...arguments)
}
}
shopObj.listen('red',function(size){
console.log(`尺寸是${size}`);
})
shopObj.listen('black',function(size){
console.log(`再次尺寸是${size}`);
})
shopObj.trigger('red',42)
shopObj.trigger('black',40)
精简版:
const event = {
list: [],
listen: function (key, fn) {
if (!this.list[key]) {
this.list[key] = []
}
this.list[key].push(fn)
},
trigger: function () {
const key = Array.prototype.shift.call(arguments)
let fn
let fns = this.list[key]
if (!fns || fns.length === 0) {
return
}
for (let i = 0; fn = fns[i]; i++) {
fn(...arguments)
}
}
}
event.listen('red', function (size) {
console.log(`尺寸是${size}`);
})
event.trigger('red',40)
数组扁平化:
将[0,1,2,[0,1,2,[6,7,8]]]变成一维数组
const num = [0,1,2,[0,1,2,[6,7,8]]]
num.flat(Infinity)
const num = [0,1,2,[0,1,2,[6,7,8]]]
const res = []
const arr = item=>{
for(let i = 0;i<item.length;i++){
if(Array.isArray(item[i])){
arr(item[i])
} else{
res.push(item[i])
}
}
}
arr(num)
BFC
BFC的理解
块级格式化上下文,他是指一个独立的块级渲染区域,只有block-level BOX参与,该区域拥有一套渲染规则来约束盒子的布局,且与区域外部无关
从一个现象开始说起
一个盒子不设置height,当内容子元素都浮动时,无法撑起自身
该盒子没有形成BFC
如何创建BFC
方法一:float的值不是none
方法二:position的值不是static或者relative
方法三:display的值时inline-block,flex或者inline-flex
方法四:overflow:hidden
BFC的其它作用
BFC可以取消盒子margin塌陷
BFC可以组织元素被其它元素覆盖
reduce
arr.reduce(function(rpev,cur,index,arr){ ... })
arr表示原数组
prev表示上一次调用回调时的返回值,或者初始值 init
cur表示当前正在处理的数组元素
index表示当前正在处理的数组元素的索引,若提供init值,则索引为0,否则索引为1
init表示初始值
上图因没设初始值,所以,pre索引为0,值为1,cur索引为1,值为2
统计名字出现的次数
const person = ['zyf','zyf','ls','pp','pp']
const nameNum = person.reduce((pre,cur)=>{
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(nameNum); //{zyf: 2, ls: 1, pp: 2}
用reduce实现数组扁平化
const array = [1,2,3,[4,5,[6,7,8]]]
const newArr = (arr)=>{
return arr.reduce((pre,cur)=>{
return pre.concat(Array.isArray(cur) ? newArr(cur) : cur)
},[])
}
console.log(newArr(array));
<script>
//构造函数继承
function Parent(name){
this.name = name
}
Parent.prototype.getName = function(){
return this.name
}
//在子类的构造函数中 执行弗雷的构造函数 并且为其绑定子类的this
function Child(){
Parent.call(this, '蔡大大')
}
const child1 = new Child()
const child2 = new Child()
child1.name = '鹿晗'
console.log(child1.name);
console.log(child2.name);
console.log(child2.getName());
//并不能继承父类原型上的方法 和 属性
</script>
寄生组合式继承
function Parent(name){
this.name = name
}
Parent.prototype.getName = function(){
return this.name
}
//在子类的构造函数中 执行弗雷的构造函数 并且为其绑定子类的this
function Child(){
Parent.call(this, '蔡大大')
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
const child1 = new Child()
const parent = new Parent()
console.log(child1.getName())
console.log(parent.getName())
提前退出提前返回
不用提前退出提前返回,就会无限if循环
function print(animal){
let result = null
if(animal){
if(animal.type){
if(animal.name){
if(animal.gender){
result = `${animal.name} is a ${animal.gender}`
}else{
result = 'no animal gender'
}
}else{
result = 'no animal name'
}
}else{
result = 'no animal type'
}
}
}
console.log(print({type: 'dog', gerder:'female'}));
用了之后
const print = ({type, name, gender})=>{
if(!type) return 'no animal type'
if(!name) return 'no animal name'
if(!gender) return 'no animal gender'
return `${name} is a ${gender} ${type}`
}
console.log(print({type: 'dog', gender:'female'}));
switch语句替换
switch语句
function printFruits(color){
switch(color){
case 'red':
return 'apple'
case 'yellow':
return 'bananas'
default:
return []
}
}
console.log(printFruits('yellow'));
改变:
const fruit = {
red:'apple',
yellow:'bananas',
green:'watermelon'
}
console.log(fruit['red']);