hans000 / javascript-note Goto Github PK
View Code? Open in Web Editor NEW前端一些小案例
Home Page: https://hans000.github.io/javascript-note/
License: MIT License
前端一些小案例
Home Page: https://hans000.github.io/javascript-note/
License: MIT License
对电话号码的中间4位做脱敏处理,例如:1881234578 -> 188****5678
function desensitize(phoneNumber) {
return phoneNumber.replace(/^(\d{3}).+(\d{4})$/, '$1****$2')
}
列出方案的具体原理
function newX(Fn, ...args) {
let obj = Object.create(Fn.prototype) // 步骤1、2
let ret = Fn.apply(obj, args) // 步骤3
return ret instanceof Object ? ret : obj // 步骤4
}
// new干了啥?
// 1、创建一个临时对象instance
// 2、维护原型链,instance.__proto__ = Func.prototype
// 3、Fn中的this指向instance,执行Fn
// 4、返回一个对象,如果显式的return一个变量,判断变量类型
// 如果是值类型,会返回这个临时对象instance;
// 函数不写默认返回undefined,undefined是值类型所以返回临时对象instance)
Function.prototype.bindX = function() {
let self = this
let [thisArg, ...args] = arguments
return function() {
self.apply(thisArg, [...args, ...arguments])
}
}
Function.prototype.callX = function () {
let [thisArg, ...args] = arguments
let fn = Symbol()
thisArg[fn] = this
let result = thisArg[fn](...args)
delete thisArg[fn]
return result
}
Function.prototype.applyX = function () {
let [thisArg, args] = arguments
let fn = Symbol()
thisArg[fn] = this
let result = thisArg[fn](...args)
delete thisArg[fn]
return result
}
说它多有用吧,真的没多大意义,仅仅是个人拿来玩的,退一万步讲,即便在某种情况下没有原生的bind,call,appay的支持,项目中也会用别人已经写好的。
如果硬要说些什么,那应该是js真的越来越好用了,要善加利用(⊙o⊙)哦
个人的一些感悟
您可以查看MDN上比较权威的实现
js中的typeof只能精确判断值类型,引用类型都视为字符串object(null也是object),这里使用Object的toString方法判断
function getType(val) {
let cfg = {
'[object Object]': 'object',
'[object Array]': 'array',
'[object Number]': 'object number',
'[object Boolean]': 'object boolean',
'[object String]': 'object string',
'[object Null]': 'null',
}
let type = typeof val
let toString = e => Object.prototype.toString.call(e)
return type === 'object' ? cfg[toString(val)] : type
}
锚点定位被顶部固定导航栏遮住,浏览器默认行为,非js滚动
// 缺点是滚动有粘滞性,似乎更适合做幻灯片效果
html {
scroll-padding-top: 60px;
}
h2::before {
content: "";
display: block;
height: 60px;
margin-top: -60px;
}
h2::target {
padding-top: 60px;
margin-top: -60px;
}
处理全屏后select、dropdown组件弹出层的层级问题。主要原因是使用requestFullscreen API会把目标元素全屏,无视其他元素的层级,目标元素是最高的(如果其他元素再次使用requestFullscreen会顶替当前的元素)
- Array.from(arrayLike[, mapFn[, thisArg]]): newArray
- Array.isArray(any): boolean
- Array.of(element0[, element1[, ...[, elementN]]]): newArray
- arr.pop(): popedElement || undefined
- arr.push(element1[, element2[, ...[, elementN]]]): newLength
- arr.reverse(): newArray
- arr.shift(): deleteElement || undefined
- arr.join([separator]): string
- arr.unshift(element1[, element2[, ...[, elementN]]]): newLength
- arr.concat(value1[, value2[, ...[, valueN]]]): newArray
- arr.entries(): newArray
- arr.every(callback(element[, index[, array]])[, thisArg]): boolean
- arr.fill(value[, start[, end]]): newArray
- arr.filter(callback(element[, index[, array]])[, thisArg]): newArray
- arr.find(callback(element[, index[, array]])[, thisArg]): matchElement || undefined
- arr.findIndex(callback(element[, index[, array]])[, thisArg]): matchIndex || -1
- arr.flat(depth): newArray
- arr.forEach(callback(element[, index[, array]])[, thisArg]): undefined
- arr.includes(searchElement[, fromIndex]): boolean
- arr.indexOf(searchElement[, fromIndex]): boolean
- arr.lastIndexOf(searchElement[, fromIndex]): boolean
- arr.map(callback(element[, index[, array]])[, thisArg]): newArray
- arr.reduce(callback(accumulator, element[, index[, array]])[, initValue]): newArray
- arr.slice([fromIndex[, toIndex]]): newArray
- arr.some(callback(element[, index[, array]])[, thisArg]): newArray
- arr.sort([compareFunction]): newArray
- arr.splice(start[, deleteCount[, element1[, element2[, ...[, elementN]]]]]): deleteArray
方案:
数组、类数组的拷贝(浅拷贝)
let [1, 2, 3, 4]
// 方式一
let copy = [...arr]
// 方式二
let copy = Array.prototype.slice.call(arr)
对象的拷贝(深拷贝)
// 代码实现
let copy = JSON.parse(JSON.stringify(obj))
//缺陷
// 不能拷贝类型为undefined、function、Symbol
// NaN视为null
// 循环引用会报错
简单的对象拷贝
// 代码实现
function simpleClone(obj) {
let copy = Array.isArray(obj) ? [] : {}
for (const key in obj) {
const elt = obj[key];
copy[key] = (typeof elt === 'object' && elt !== 'null')
? simpleClone(elt)
: elt
}
return copy
}
// 缺陷
// 循环引用会爆栈RangeError
标题 | 分类 |
---|---|
锚点定位被顶部固定导航栏遮住(仅CSS) | layout |
取消浏览器对页面滚动条位置的记录 | css |
flex内容溢出问题 | css |
处理全屏后select、dropdown组件弹出层的层级问题 | css |
就拿写的游戏的案例举例
游戏中的基类
function Sprite(posX=0, posY=0, width=10, height=10) {
this.posX = posX
this.posY = posY
this.width = width
this.height = height
this.color = ['red', 'blue']
}
Sprite.prototype = {
render() {
console.log('this is a render function')
},
update() {
console.log('this is a update function')
}
}
// 功能实现
function Ball(vx, vy) {
this.vx = vx
this.vy = vy
}
Ball.prototype = new Sprite() // 缺陷2、3
// 使用
let ball = new Ball(0.1, 0.1) // 缺陷1
ball.posX = 10
ball.posY = 10
ball.width = 50
ball.height = 50
ball.color.push('black') // 缺陷3
let ball2 = new Ball(0.2, 0.2)
// 缺陷:
// 1、实例化子类时无法向父类构造函数传参,期望是new Ball(10, 10, 50, 50, 0.1, 0.1)
// 2、单一继承
// 3、子类共享父类实例属性
// 功能实现
function Ball(posX, posY, width, height, vx, vy) {
Sprite.call(this, posX, posY, width, height)
this.vx = vx
this.vy = vy
}
// 使用
let ball = new Ball(100, 100, 50, 50, 0.1, 0.1)
// 缺陷:
// 1、子类无法继承父类原型上的属性、方法
// 2、无法实现构造函数的复用,每次实例化都会重新调用
// 3、每个实例都有父类构造函数的副本,臃肿
// 功能实现
function Ball(posX, posY, width, height, vx, vy) {
Sprite.call(this, posX, posY, width, height) // 第一次
this.vx = vx
this.vy = vy
}
Ball.prototype = new Sprite() // 第二次
// 使用
let ball = new Ball(100, 100, 50, 50, 0.1, 0.1)
ball.color.push('black')
et ball2 = new Ball(200, 200, 20, 20, 0.2, 0.2)
// 缺陷:
// 调用了两次构造函数
// 功能实现
Ball.prototype = Sprite.prototype
Ball.prototype.canMove = true
function Ball(vx, vy) {
this.vx = vx
this.vy = vy
}
// 缺陷:
// 1、实例化子类时无法向父类构造函数传参
// 2、单一继承
// 3、修改子类原型会修改父类原型
// 4、子类无法继承父类构造函数的属性
// 功能实现
Ball.prototype = Object.create(Sprite.prototype)
Ball.prototype.constructor = Ball
Ball.prototype.canMove = true
function Ball(posX, posY, width, height, vx, vy) {
Sprite.call(this, posX, posY, width, height)
this.vx = vx
this.vy = vy
}
// 使用
let ball = new Ball(100, 100, 50, 50, 0.1, 0.1)
ball.color.push('black')
let ball2 = new Ball(200, 200, 20, 20, 0.2, 0.2)
// 功能实现
class Sprite {
constructor(posX, posY, width, height) {
this.posX = posX
this.posY = posY
this.width = width
this.height = height
}
render() {
console.log('this is a render function')
}
update() {
console.log('this is a update function')
}
}
class Ball extends Sprite {
constructor(vx, vy, ...args) {
super(...args)
this.vx = vx
this.vy = vy
}
}
个人理解
如果不使用原型,就会有不能复用、每个子类实例都有父类的问题
直接给子类原型赋值就会有单一继承的问题
父类原型直接给子类原型就会造成修改子类原型也同时修改了父类原型
只使用父类原型就会有子类不能继承父类构造函数属性的问题
如果不使用call / apply,传参问题就不能解决
call / apply不仅可以解决传参问题,还可以解决单一继承问题
原型就是为了解决一些公共属性和方法
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.