var virtualDom = {
tag: 'DIV',
attrs: {
id: 'app'
},
children: [{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] }
]
}, {
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] },
]
}]
}
function render(dom) {
let node = null
if (dom.tag) {
node = document.createElement(dom.tag.toLowerCase())
}
if (dom.attrs && Object.keys(dom.attrs)) {
Object.keys(dom.attrs).forEach(key => {
node.setAttribute(key, dom.attrs[key] || '')
})
}
if (dom.children && dom.children.length) {
dom.children.forEach(child => node.appendChild(render(child)))
}
return node
}
var element = render(virtualDom)
// console.log(element)
var a1 = [1,2,3,4,[5,[6]]]
function useWhile (arr) {
while(arr.some(v => Array.isArray(v))) {
arr = [].concat(...arr)
}
console.log('useWhile ', arr)
return arr
}
// useWhile(a1)
const obj = {
a: {
b: 1,
c: {},
d: {e: 3}
},
b: [1,2, {a: 3, b: []}],
c: 3,
d: []
}
function demo(data) {
const result = {}
function format(value, key) {
// 基础类型
if (typeof value !== 'object') {
key && (result[key] = value)
} else if (Array.isArray(value)) {
value.forEach((v, i) => {
format(v, key ? `${key}.${i}` : i)
})
// 空数组
if (value.length === 0) {
result[key] = value
}
} else {
Object.keys(value).forEach(k => {
format(value[k], key ? `${key}.${k}` : k)
})
// 空对象
if (Object.keys(value).length === 0) {
result[key] = value
}
}
}
data && format(data, '')
console.log('result ', result)
return result
}
// demo(obj)
const arr1 = [
{id:"01", name: "张大大", pid:"", job: "项目经理"},
{id:"02", name: "小亮", pid:"01", job: "产品leader"},
{id:"03", name: "小美", pid:"01", job: "UIleader"},
{id:"04", name: "老马", pid:"01", job: "技术leader"},
{id:"05", name: "老王", pid:"01", job: "测试leader"},
{id:"06", name: "老李", pid:"01", job: "运维leader"},
{id:"07", name: "小丽", pid:"02", job: "产品经理"},
{id:"08", name: "大光", pid:"02", job: "产品经理"},
{id:"09", name: "小高", pid:"03", job: "UI设计师"},
{id:"10", name: "小刘", pid:"04", job: "前端工程师"},
{id:"11", name: "小华", pid:"04", job: "后端工程师"},
{id:"12", name: "小李", pid:"04", job: "后端工程师"},
{id:"13", name: "小赵", pid:"05", job: "测试工程师"},
{id:"14", name: "小强", pid:"05", job: "测试工程师"},
{id:"15", name: "小涛", pid:"06", job: "运维工程师"}
]
// 数组转树
function arr2tree(data) {
const root = []
const map = data.reduce((cur, pre) => ({...cur, [pre.id]: pre}), {})
// console.log(map)
for (const item of data) {
const parent = map[item.pid]
if (parent) {
if (!parent.children) {
parent.children = []
}
parent.children.push(item)
} else {
root.push(item)
}
}
console.log(root)
}
// arr2tree(arr1)
function arr2tree2(data, pid) {
return data.filter(v => v.pid === pid).map(v=> ({...v, children: arr2tree2(data, v.id)}))
}
// console.log(arr2tree2(arr1, ''))
const treeData = [
{
id: 2, title: '中国', pid: 0,
children: [
{
id: 3, title: '广东省', pid: 2,
children: [
{
id: 4, title: '广州市', pid: 3,
children: [
{ id: 5, title: '天河区', pid: 4 }
]
}
]
},
{ id: 6, title: '湖南省', pid: 2 }
]
},
{ id: 1, title: '俄罗斯', pid: 0 },
]
// 树转数组
function getChild(nodes) {
const res = []
for (const item of nodes) {
const {children, ...rest} = item
res.push(rest)
if (children && children.length) {
res.push(...getChild(item.children))
}
}
return res
}
function tree2arr(nodes) {
return nodes.reduce((cur, pre) => {
const {children, ...rest} = pre
return cur.concat(rest, Array.isArray(children) ? tree2arr(children) : [])
}, [])
}
// console.log(tree2arr(treeData))
// console.log(getChild(treeData))
// 模拟Object.create
function objCreate(proto) {
function F() {}
F.prototype = proto
return F
}
// 模拟实现instanceof
function instanceof2(left, right) {
const o = right.prototype
left = left.__proto__
if (left === null) {
return false
}
return left === o
}
// 深度克隆
var s = {
a: 1,
b: function () {
console.log('b123');
},
c: 'is c',
d: {
e: null,
f: {
g: undefined,
}
},
h: [1, 2, 3]
};
function cloneDeep(data) {
if (typeof data !== 'object') {
return data
}
let child = data instanceof Array ? [] : {}
for (const key in data) {
const val = data[key]
child[key] = typeof val !== 'object' ? val : cloneDeep(val)
}
return child
}
const newObj = cloneDeep(s)
newObj.d.f.g = 123
// console.log(newObj)
// console.log(s)
// bind call apply
var cat = {
type: 'cat',
name: 'miaomiao'
}
function animal(age, tall) {
console.log(`tall = ${tall}`)
console.log(`${this.name} is a ${this.type}, ${age} years old.`)
}
// bind
Function.prototype.bind2 = function(ctx) {
const context = ctx || window
context.fn = this
const args = arguments.splice(1)
return function() {
context.fn(...args, ...arguments)
delete context.fn
}
}
// animal.bind(cat)(2)
// call
Function.prototype.call2 = function(ctx) {
const context = ctx || window
context.fn = this
const result = context.fn(...arguments)
delete context.fn
return result
}
// animal.call(cat)
// apply
Function.prototype.apply2 = function(ctx, params = []) {
const context = ctx || window
context.fn = this
const result = context.fn(params)
delete context.fn
return result
}
// animal.apply(cat, [11, 12])
// 防抖
function debounce(fn, delay) {
let timer = null
return function(...args) {
timer && clearTimeout(timer)
timer = setTimeout(() => {
fn && fn.apply(this, args)
}, delay)
}
}
// 节流
function throttle(fn, delay) {
let latest = 0
return function(...args) {
const now = Date.now()
if (now - latest > delay) {
fn && fn.apply(this, args)
latest = now
}
}
}
// reduce 实现filter
var f = [1,2,3,4,5,6]
Array.prototype.filter2 = function(callbak) {
return this.reduce((cur, pre) => {
return cur.concat(callbak && callbak(pre) ? pre : [])
}, [])
}
// console.log(f.filter2(v => v > 4))
// filter
Array.prototype.filter3 = function(callback) {
const result = []
for (let i = 0; i < this.length; i++) {
if (callback && callback(this[i], i, this)) {
result.push(this[i])
}
}
return result
}
// console.log(f.filter3(v => v > 3))
// some
Array.prototype.some1 = function(callbak) {
let result = false
for (let i = 0;i<this.length;i++) {
if (callbak && callbak(this[i], i, this)) {
result = true
break
}
}
return result
}
// console.log(f.some1(v => v >4))
// every
Array.prototype.every1 = function(callback) {
let total = 0
for (let i=0;i<this.length; i++) {
if (callback && callback(this[i], i, this)) {
total += 1
}
}
return total === this.length
}
// console.log(f.every1(v => v > 4))
// map
Array.prototype.map1 = function(callback) {
const result = []
for (let i =0; i< this.length; i++) {
result.push(callback && callback(this[i], i, this))
}
return result
}
// console.log('map => ', f.map(v => v > 1))
// console.log('map1 => ', f.map1(v => v > 1))
// 字符模板
var str = 'test/action?name=${name}&age=${age}';
var strObj = {
name: 'jack',
age: 20
}
function renderTpl(tpl, obj) {
Object.keys(obj).forEach(key => {
// const reg = new RegExp("\\${"+key+ "}", 'g')
const reg = new RegExp(`\\$\{${key}\}`, 'g')
tpl = tpl.replace(reg, obj[key])
// tpl = tpl.replace(/\$\{(.*?)\}/g, obj[key])
})
return tpl
}
// console.log(renderTpl(str, strObj))
// 继承 组合式
function Person(name) {
this.name = name
this.say = function() {
console.log(`my name is ${this.name}`)
}
}
function Child(age) {
Person.call(this, age)
}
Child.prototype = new Person()
Child.prototype.constructor = Child
// const c = new Child(11)
// c.name = 'jack'
// c.say()
// 继承 寄生组合式
function Child2(age) {
}
Child2.prototype = Object.create(Person)
Child2.prototype.constructor = Child2
console