Giter VIP home page Giter VIP logo

javascript-note's People

Contributors

hans000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

javascript-note's Issues

手写一个函数实现new关键字的功能

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)

处理全屏后select、dropdown组件弹出层的层级问题

问题描述

处理全屏后select、dropdown组件弹出层的层级问题。主要原因是使用requestFullscreen API会把目标元素全屏,无视其他元素的层级,目标元素是最高的(如果其他元素再次使用requestFullscreen会顶替当前的元素)

解决方案

  • 把弹出层设置到元素下面(如果条件允许)
  • 设置body为全屏,然后设置目标元素的样式使其撑满页面

锚点定位被顶部固定导航栏遮住(仅CSS)

问题描述

锚点定位被顶部固定导航栏遮住,浏览器默认行为,非js滚动

解决方案

  • 滚动元素设置 scroll-padding-top
// 缺点是滚动有粘滞性,似乎更适合做幻灯片效果
html {
  scroll-padding-top: 60px;
}
  • margin-top负值
h2::before {
    content: "";
    display: block;
    height: 60px;
    margin-top: -60px;
}

h2::target {
    padding-top: 60px;
    margin-top: -60px;
}

参考链接

链接

js中对象的拷贝

数组、类数组的拷贝(浅拷贝)

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

常用数组API

- 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

封装一个完善的typeof

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
}

分别用6行代码实现bind、call和apply

命名为bindX、callX、applyX

bind

Function.prototype.bindX = function() {
  let self = this
  let [thisArg, ...args] = arguments
  return function() {
    self.apply(thisArg, [...args, ...arguments])
  }
}

call

Function.prototype.callX = function () {
  let [thisArg, ...args] = arguments
  let fn = Symbol()
  thisArg[fn] = this
  let result = thisArg[fn](...args)
  delete thisArg[fn]
  return result
}

apply

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⊙)哦

个人的一些感悟

  • 保存当前对象this
  • 保存绑定对象thisArg
  • 保存剩余参数
  • 根据具体功能处理
    • bind 返回的是函数
    • call 返回的是函数执行的结果,剩余参数是展开形式
    • apply 返回的是函数执行的结果,剩余参数是数组形式

您可以查看MDN上比较权威的实现

号码脱敏

问题描述

对电话号码的中间4位做脱敏处理,例如:1881234578 -> 188****5678

解决方案

function desensitize(phoneNumber) {
    return phoneNumber.replace(/^(\d{3}).+(\d{4})$/, '$1****$2')
}

参考链接

列出方案的具体原理

js中的6种继承

就拿写的游戏的案例举例

游戏中的基类

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)
  • ES6 extends
// 功能实现
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不仅可以解决传参问题,还可以解决单一继承问题

  • 原型就是为了解决一些公共属性和方法

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.