RecordYu

RecordYu 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

不想明白为何而停前,可能得要一直跑着吧

个人动态

RecordYu 发布了文章 · 9月15日

自定义call&apply&bind的实现

仿造原生js的call,apply,bind的原理自定义绑定this的工具函数

实现思路:大致是改变函数执行环境中this的指向,这个this的指向根据谁调用了这个函数来决定,如果将这个函数成为某个对象方法,this就和这个对象进行了绑定。
注意:在自定义的函数中记得返回被调用的函数(this发生改变)其返回值,如果传入的对象是null或者undefined,则被调用的函数this指向window。
代码实现:
function Call (Fn,obj,...argument) {

 // 如果obj是null或者undefined,Fn的this指向window,所以由window来调用

 if (obj === undefined || obj === null) {

 obj = window

 }

 // 1.给obj添加一个属性,值为Fn,目的是改变this指向

 obj.tempFun = Fn

 // 2.调用该函数,改变执行环境中this的指向

 let result = obj.tempFun(...argument)

 // 3.删除obj添加的方法

 delete obj.tempFun

 // 4.返回函数执行的返回值

 return result

 }

 function Apply (Fn,obj,argument) {

 // 两者只是传参的形式不同,在函数体里调用自定义的Call函数,参数解构赋值即可

 return Call(Fn,obj,...argument)

 }

 function Bind (Fn,obj,...argument) {

 return function(...argument2) {

 Call(Fn,obj,...argument,...argument2)

  }

 }

验证结果:
function fn (a,b) {

 console.log(a,b,this)

 }

 let person = {name:'zhangsan',age: 10}

 fn(1,2)

 Call(fn,person,1,2)

 Call(fn,undefined,1,2)

 Apply(fn,person,[1,2])

 Apply(fn,null,[1,2])

 let bindFun = Bind(fn,person)

 bindFun(3,4)

image.png

查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 9月11日

手写实现深拷贝

深拷贝和浅拷贝的区别

1.当拷贝到值是对象或数组时,浅拷贝只复制了值的引用,没有将对象所占的内存完全拷贝下来。基本数据类型可直接复制。
判断点:当拷贝对象数据类型时,可以看是否产生了新的数据还是只是复制了值的引用。

代码实现

 // 判断数组或对象类型

 function cloneType (target) {

 return Object.prototype.toString.call(target).slice(8,-1)

 }

  

 // 深拷贝

 function cloneDeep (target) {

 let result

 if (cloneType(target) === 'Object'){

 result = {}

 }else if (cloneType(target) === 'Array') {
 
 result = []
 
 }

 else {
 
    result = target
    
 }

 for(let i in target) {

 let item = target[i]

 if (cloneType(item)==='Object' || cloneType(item) ==='Array' ) {

 result[i] = cloneDeep(item)

 }else {

    result[i] = item

   } 

 }

 return result

}
验证结果
 let person = {name: 'zhangsan', age: 13, 

 option:{

 sex:'man',

 fav:'football'

 }

 }

 let person2 = cloneDeep(person)

 console.log(person2)

 console.log('---------------')

 person.option.sex = 'woman'

 console.log(person2)

image.png

实现思路
1.主要是通过递归的思想来实现,要判断当前拷贝是什么数据类型,来决定函数要返回什么样的数据类型。
2.接着如果确定是对象数据类型之后再判断里面是否还有引用类型的数据,若有则重复之前的步骤直到拷贝的是基本数据类型。
查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 9月10日

手写new创建对象的过程

仿造new创建对象的过程写一个函数实现

1.创建一个对象
2.执行构造函数,将this指向刚才创建的对象
3.如果该构造函数有返回值,且为对象类型,则直接返回该对象
4.将obj的__proto__指向构造函数的prototype,并将obj的__proto__下的constructor指向构造函数
5.返回创建的对象

代码如下:

 function newInstance (Fn,...argument) {

 // 1.创建一个空对象

 const obj = {}

 // 2.执行构造函数,并将this指向obj

 const result = Fn.call(obj,...argument)

 // 3.如果该构造函数的返回值是Object类型则返回该对象

 if (result instanceof Object) {

 return result

 }

 // 4.将obj的_proto_指向构造函数的prototype,并将obj的_proto_下的constructor指向构造函数

 obj.__proto__ = Fn.prototype

 obj.__proto__.constructor = Fn

  
 // 返回该对象

 return obj

 }

验证实现效果:

 function Person (name, age) {

 this.name = name

 this.age = age

 }

 Person.prototype.type = 'human' 

 let person = newInstance(Person,'wade',42)

 console.log(person)

image.png

查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 6月9日

函数节流和防抖的实现

函数防抖

何为函数防抖

定义:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;
如何理解这段定义,可以用手机屏幕休眠来理解,若设置休眠时间为一分钟,如果在一分钟之内我们有去操作手机,则重新从一分钟开始计算。
这个过程中,事件可为触摸屏幕,然后事件被触发后的一分钟后屏幕休眠,但是在这一分钟内如果又触摸了屏幕,则会重新从一分钟开始计算。

如何实现函数防抖

应用场景:函数防抖一般应用于搜索框,用函数防抖来实现收集数据发送请求
eg.

let input = document.querySelector('input')
let timeID = null // 设置控制定时器的句柄
input.onkeyup = () => {
  if (timeID) {
    clearTimeout(timeID) // 如果有在延迟时间内再次触发,则清除定时器
  }
   timeID = setTimeout(() => {
    console.log(input.value,'获取搜索框内容')
  }, 200);
}

何为函数节流

定义:指连续触发事件但是在 n 秒中只执行一次函数。
字面意思就是在一段周期内,事件被触发多少次,它所指定的回调函数只执行一次
主要是用来避免一些频繁操作

如何实现函数节流

eg.

let btn = document.querySelector('#btn')
let flag = true
btn.onclick = () => {
  if (flag) {
    console.log('发送请求')
    flag = false  
    setTimeout (()=>{
    flag = true 
  },2000) // 设定周期
 }
}
查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 6月6日

CSS的BFC以及应用

CSS的BFC是什么

BFC(Block Formatting Context)块级格式化上下文

首先格式化上下文是一套css规范定义的页面渲染区域,有自身的渲染规则(定位,子元素之间的关系)
那么BFC便是格式化上下文中的其中一种,可将拥有BFC特性的元素看成一个大容器,里面的子元素布局
不会影响到外面的元素

元素如何拥有BFC特性

  1. 当元素是html根元素时便自动拥有BFC特性
  2. 当元素被设置成绝对定位的元素(position: fixed , absolute)
  3. 当元素设置成除了float:none 元素之外的浮动元素
  4. 当元素设置了overflow属性,并且值不为visible

如何应用元素的BFC特性

  1. 解决上下外边距重叠的问题
    原因:当我们定义两个块级元素,它们之间的上下边距会重叠
    这是由于根元素拥有BFC特性,会将两个块级元素的上下外边距进行重叠
    解决:若想让它们之间的上下边距不重叠,则要对它们分别拥有BFC特性

      eg.  <div style="overflow: hidden"></div>
         <div style="overflow: hidden"></div>
      这样两个元素便会独立开来,不会发生上下外边距的重叠了
    
  2. 清除浮动,解决由于浮动带来的父元素高度坍塌的问题
    原因:由于父元素没有设置高度,子元素设置成浮动后,会脱离普通文档流,让父元素高度塌陷
    解决:由于BFC容器可以包含浮动元素,所以可以触发父元素的BFC属性

     eg. <div style="overflow: hidden">
              <div style="float:left; height:200px"></div>
          </div>
    
  3. 处理元素被浮动元素覆盖
    原因:设置为浮动元素其兄弟元素会被覆盖
    解决:将兄弟元素追加BFC特性,可以和浮动元素隔离开来,不被其覆盖

      eg. <div style="overflow: hidden">content</div>
            <div style="float:left; width:200px; height:200px"></div>
    
查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 4月19日

es6-关于原生JS继承到class继承的实现

继承的特点

1.继承可以实现构造函数代码的复用
2.子类可以获取父类的一般方法,不用重复定义

在es6的class出现之前,原生js如何实现继承

1.通过原型进行继承
2.在子类构造函数中调用父类的构造函数
两者组合使用实现继承效果
为了清晰继承关系,先用父类,子类来表示构造函数

 // 父类 定义一个学生的构造函数
  function Student(name,age) {
    this.name = name
    this.age = age
  }
  // 给父类 学生实例对象添加一个方法
  Student.prototype.study = function () {
    console.log('学习')
  }
  
  // 子类 定义一个大学生的构造函数
  function collegeStu (name,age,school) {
    // 此时可以调用父类的构造函数减少相同代码,但要注意改变this的指向
    /* this.name = name
    this.age = age */
    Student.call(this,name,age) //若不指定this,直接调用父类的构造函数,this会指向window
    this.school = school
  }

由于子类构造函数的显式原型链上没有设置study方法,
所以要想使用父类study方法则要改变子类显式原型链的指向
collegeStu1._proto_ === collegeStu.prototype 没有study

student1._proto_ === Student.prototype 有study

要想找到study方法,就让这个{collegeStu.prototype}对象成为Student的实例对象
这样就能够让collegeStu1._proto_顺着原型链找到Student的实例对象,Student的实例的_proto_中就会有study这个方法

    let student1 = new Student('小明',10)
    student1.study() // 学习
 // 让子类 大学生的显式原型成为父类 学生的实例对象,同时将构造器(校正)指向子类构造函数本身
    collegeStu.prototype = new Student ()
    collegeStu.prototype.constructor = collegeStu
    let collegeStu1 = new collegeStu('小华',20,'xxx大学')
    collegeStu1.study() // 继承父类的方法 学习

运行结果

继承.PNG

上述是原生JS的继承,ES6中class才实现了真正意义上的类

class定义的类

1.本质上构造函数只是函数而已,并不是真正的类
2.用class定义一个类,对象中会包含一个constructor方法,相当于一个构造函数,也称为构造器,在其中子类可以用super()函数调用父类的构造方法
4.类中也可以定义一般的方法,相当于构造函数.prototype去定义方法

class类实现原型继承,代替原生js写法

class Student{
   constructor(name,age){
        this.name = name
        this.age = age
    }
      study(){
        console.log('学习')
      }
  }

  class collegeStu extends Student{
    constructor(name,age,school){
        super(name,age)
        this.school = school
    }
  }
  
  let student1 = new Student('小明',10)
  student1.study() // 学习

  let collegeStu1 = new collegeStu('小华',20,'xxx大学')
  collegeStu1.study() // 继承父类的方法 学习

class一点补充

1.extends 是对 子构造函数.prototype = new 父构造函数 () 的进一步底层封装并加以优化
2.在类中定义供自身使用而不给实例对象使用的静态方法用static来定义
3.可在子类中重写父类的一般方法,但不会影响父类的方法使用

查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 4月17日

es6-关于箭头函数的用法和this指向

箭头函数的特点

1.书写风格简洁
2.当函数的功能简单且能用一行语句或表达式表示时使用箭头函数能节省代码量提升开发效率
3.箭头函数自身的this指向能自动绑定外部函数的this指向,不用开发者进行人为地绑定;方便进行相应的this操作

箭头函数的使用

箭头函数的表示

let fun = () => {函数体}; let fun2 = (形参) => {函数体}
1.当没有形参时,小括号不能省略
2.当形参只有一个时,()可以省略不写,当有多个形参时,()必须写上
3.当函数体内只需要一条语句或者表达式时,{}可以省略,当有多条语句或表达式时,{}则不能省略
let fun3 = item => item>1 ? item++ : item--

箭头函数返回值

当箭头函数的函数体没有用{ }时,会默认将内部函数执行结果作为返回值,且不能够人为加下return关键字
eg

   let fun = () => 1+1
   console.log(fun()) // 2 

   let fun2 = () => {1+1}
   console.log(fun2()) //undefined

箭头函数的this指向

1.箭头函数的this不是在调用的时候决定的,而是在定义的时候决定的
2.箭头函数的this指向首先看其外部有没有函数,
1)如果有,它的this指向和这个外部函数绑定,当外部函数被调用时, this指向哪里,箭头函数则指向哪里。
2)如果没有外部函数,则箭头函数的this指向Window
eg

  //没有外部函数时
  let obj = {
    fun1: function(){
       console.log(this) // this->{obj}
    },
    fun2: ()=>{
        console.log(this) // this->{Window} 
    }
  }
  //使用常规函数定义,函数this指向由调用时决定,fun1被obj调用,函数this指向obj
  obj.fun1() 

  //使用箭头函数定义,函数this指向由定义时决定,fun2外部没有函数,所以this指向Window
  obj.fun2() 
// 有外部函数时
  let obj2 = {
    fun3: function(){
      console.log(this) // this->{obj2}; 当obj2.fun3.call(obj) this->{obj} 
      let fun4 = () => {console.log(this)} //this->{obj2}; 当obj2.fun3.call(obj) this->{obj} 
      fun4()
    }
  }
  obj2.fun3() //箭头函数fun4()外部有一个函数fun3(),this指向和它绑定,当fun3被调用时this指向哪里,箭头函数this就指向哪里
  obj2.fun3.call(obj) //调用fun3时改变this指向,其内部的箭头函数fun4的this指向也发生改变

箭头函数注意点

箭头函数被调用时的this指向不能够通过call,apply,bind进行绑定,
由于箭头函数的this在定义的时候就决定了,所以不能在其被调用时进行改变

查看原文

赞 0 收藏 0 评论 0

RecordYu 发布了文章 · 4月17日

ES6-学习总结-关于let,const关键字

let与var的区别

1.let不存在变量提升,即不会进行预解析
2.使用let不能重复定义相同的变量
3.用let创建变量会产生一个块级作用域

let的应用场景

当用for循环来绑定事件监听时,使用let会比用闭包写更加简洁
1.使用闭包写

  for(var i=0; i<btn.length; i++){
      (function(i){
        btn[i].onclick = function () {
          alert(i)
        }
    })(i)
   }

在绑定事件之前先创建一个立即执行函数,将 i 传进去。
最后生成了3个闭包

2.使用let关键字写

   for(let i=0; i<btn.length; i++){
     btn[i].onclick = function (){
       alert(i)
     }
   }

使用let在进入循环时会创建一个作用域,最后会有三个作用域来保存 i 变量

const关键字

1.作用:用来保存不能被改变的常量,常量一般用大写字母表示
2.使用const定义一个常量后,该常量不能够再次被修改

查看原文

赞 0 收藏 0 评论 0

RecordYu 关注了专栏 · 4月16日

思否编程公开课

思否编程打造全新公开课系列,邀请大神级讲师分享技术干货,快来围观看直播

关注 8404

RecordYu 关注了专栏 · 4月16日

终身学习者

我要先坚持分享20年,大家来一起见证吧。

关注 40220

认证与成就

  • 获得 0 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 4月16日
个人主页被 140 人浏览