一些笔记(一)

一、手写Bind函数

bind函数:bind() 方法创建一个新的函数, 当这个新函数被调用时其this置为提供的值,其参数列表前几项置为创建时指定的参数序列。它的一个用处就是用来改变函数this指向。

总的来说bind有如下三个功能点:

1.改变原函数的 this 指向,即绑定上下文,返回原函数的拷贝
2.当 绑定函数 被调用时,bind的额外参数将置于实参之前传递给被绑定的方法。
3.注意,一个 绑定函数 也能使用 new 操作符创建对象,这种行为就像把原函数当成构造器,thisArg 参数无效。也就是 new 操作符修改 this 指向的优先级更高。

TIS:关于this

This的四种绑定规则

1.默认绑定

指向全局对象

2.隐式绑定

绑定到这个上下文对象

3.显示绑定

运用apply call 方法,在调用函数时候绑定this,也就是指定调用的函数的this值

4.new绑定

就是使用new操作符的时候的this绑定

上述四条规则优先级由上到下依次递增。

BIND函数:

输入:接受一个或者多个参数,第一个是要绑定的上下文,额外参数当作绑定函数的前置参数。

输出:返回原函数的拷贝,即返回一个函数,这个函数呢具备原函数的功能

// 定义这个方法为myBind
Function.prototype.myBind = function(thisArg) {
  if (typeof this !== 'function') {
    return;
  }
  var _self = this;
  var args = Array.prototype.slice.call(arguments, 1) //从第二个参数截取
  return function() {
    return _self.apply(thisArg, args.concat(Array.prototype.slice.call(arguments))); // 注意参数的处理
  }
}

到此实现上下文功能以及参数功能还不能实现NEW关键词功能

我们先考虑一下new操作符在调用构造函数时做了哪些操作?

比如说 var a = new b()

{} .__proto__ = b.prototype

所以我们做了如下修改:

Function.prototype.myBind = function(thisArg) {
  if (typeof this !== 'function') {
    return
  }
  var _self = this
  var args = Array.prototype.slice.call(arguments, 1)
  var fnNop = function () {} // 定义一个空函数
  var fnBound = function () {
    var _this = this instanceof _self ? this : thisArg

    return _self.apply(_this, args.concat(Array.prototype.slice.call(arguments)))
  }
  // 维护原型关系
  if (this.prototype) {
    fnNop.prototype = this.prototype;
  }

  fnBound.prototype = new fnNop();

  return fnBound;
}

二、new操作符具体干了什么

var obj  = {}; 

第一行,我们创建了一个空对象obj

obj.__proto__ = Base.prototype;

第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象

Base.call(obj);

将构造函数的this通过apply、call指向中间对象。返回该中间对象,也就是返回了实例对象

三、前端路由

(1). 分类

浏览器支持的两种前端路由方式分别是hash、history。通俗的讲带#的就是hash路由。

优缺点对比:hash

优点:兼容性好,不许要服务端支持

缺点:带#,不符合人类审美,会被一些有洁癖的甲方爸爸diss

history

优点:符合人类审美

缺点:开发成本,需要服务端支持。有些前端不太了解nginx配置或者SpringMVC路由的写法,后端不支持的话只能自己搞,不过这是个一劳永逸的工作。

(2)原理

hash路由

  1. 当url的hash改变时,即浏览器的地址栏#后面的内容改变时,页面不会刷新,浏览器不会像后端发送页面请求。前端要做的就是改变hash和监听hashchange事件。

  2. 更改hash的代码:

    window.location.hash = '#a'

    window.location.replace('#b')

    上面两行代码可以随便在哪个网站打开控制台试一下。

  3. 监听hashchange代码:

    window.addEventListener('hashchange', () => document.getElementById('root').innerHTML = 'hash has change')

history路由

  1. HTML5 规范中提供了 history.pushState 和 history.replaceState 来进行路由控制。 通过这两个方法,可以实现改变 url 且不向服务器发送请求。

  2. 更改history的代码:

    history.pushState({}, '', '/a')

    history.replaceState({}, '', '/b')

    上面两行代码可以随便在哪个网站打开控制台试一下。

  3. 监听history change:

    这个有点麻烦,不像hash一样有一个现成的hashchange方法。考虑到更改history只有两种方式:浏览器的前进后退、通过上面两行代码触发,所以可以对这两种方式进行回调处理:

  4. 浏览器的后退/前进:触发popstate事件

  5. window.addEventListener('popstate', handleHref);

  6. history.pushState/history.replaceState:同步事件,直接把popstate的回调函数写在后面就可以。

    history.pushState({}, '', '/a');

    handleHref();

  7. 回调函数:

    function handleHref () {document.getElementById('app').innerHTML = 'history has change' }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值