前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我不知道的前端(三)

我不知道的前端(三)

作者头像
源心锁
发布2022-08-12 11:31:15
2910
发布2022-08-12 11:31:15
举报
文章被收录于专栏:前端魔法指南

记录我的学习笔记,本篇之前都是JavaScript相关的内容

prototype和proto的灵活应用

想必时间戳的各种转换需求大家见到的不算少,有时候封装一个方法非常有必要。 下边是一个format方法,可以让我们用期望的格式将Date对象转换为String

代码语言:javascript
复制
Date.prototype.format = function (format) {
  var o = {
    "M+": this.getMonth() + 1,
    "d+": this.getDate(),
    "h+": this.getHours(),
    "m+": this.getMinutes(),
    "s+": this.getSeconds(),
    "q+": Math.floor((this.getMonth() + 3) / 3),
    "S": this.getMilliseconds()
  }
  if (/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (this.getFullYear() + "")
      .substr(4 - RegExp.$1.length));
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] :
        ("00" + o[k]).substr(("" + o[k]).length));
    }
  }
  return format;
}

调用

代码语言:javascript
复制
new Date().format("yyyy-MM-dd hh:mm:ss")
image.png
image.png

同理的,除了Date,我们也可以尝试为各种内置类添加各种实用的方法,有一个专门的prototype.js扩展库就为内置类添加了很多的实用方法。

使用上边的方法你会发现,你可以调用一个实例化Date对象的format方法,但是Date.format()是行不通的 这是自然的,想做到Date.format这种看着很像静态方法的操作(实际应用场景中其实没有所谓Date.format,常规需求里应该是希望有个类似于Array.range()的函数) 而想这么做的话,我们就需要使用下边这种方式:

代码语言:javascript
复制
Array.__proto__.range=function(a,b){
  let arr=[]
  if (a>b) {
    for (let index = a; index >= b; index--) {
      arr.push(index)
    }
  }else{
    for (let index = a; index < b; index++) {
      arr.push(index)
    }
  }
  return arr;
}

其实回过头来看,所谓的类就是一个构造函数,对应Date.__proto__其实就是Function.prototype

javascript中children和childNodes的区别

1,childNodes:它是标准属性,它返回指定元素的子元素集合,包括HTML节点,所有属性,文本节点。 可以通过nodeType来判断是哪种类型的节点,只有当nodeType==1时才是元素节点,2是属性节点,3是文本节点。

有些人错误的使用()去取该集合元素,下表列出各浏览器对childNodes(i)的支持情况:

IE6/7/8/Safari/Chrome/Opera IE9/Firefox childNodes(i) 支持 不支持 有时候需要获取指定元素的第一个HTML子节点(非属性/文本节点),最容易想到的就是firstChild 属性。代码中第一个HTML节点前如果有换行,空格,那么firstChild返回的就不是你想要的了。可以使用nodeType来判断下。

代码语言:javascript
复制
function getFirst(elem){
    for(var i=0,e;e=elem.childNodes[i++];){
        if(e.nodeType==1)
            return e;
    }
}

2,children:非标准属性,它返回指定元素的子元素集合。 但它只返回HTML节点,甚至不返回文本节点,虽然不是标准的DOM属性,但它和innerHTML方法一样,得到了几乎所有浏览器的支持。

和childNodes 一样,在Firefox下不支持()取集合元素。因此如果想获取指定元素的第一个HTML节点,可以使用children[0]来替代上面的getFirst函数。

这里需要注意的是children在IE中包含注释节点

this指向

this究竟绑了谁

this的作用域并不取决于代码在哪书写,而是在运行时才进行绑定。当然我们可以用bind函数硬修改this的作用域,这是我觉得非常实用的函数。

绑定规则

我们说js里所有东西都是对象

  • 默认绑定 我们写一个独立的函数进行调用 function foo(){ console.log(this.a) } var a=2; foo();//2 复制代码 (类似这样的代码阅读体验非常差劲,但是我们可以从中学习一些js底层) 这里的a声明在全局作用域中,所以被挂载到了全局对象上去。 当我们调用this.a时,this指向全局对象故而输出2; 整理一下这种情况的调用情况:
    • foo()在全局作用域中调用
    • foo()是直接调用
  • 隐式绑定 如果我们把函数放到某一个对象里 function foo(){ console.log(this.a); } var obj={ a:2, foo } obj.foo();//2 foo();//undefined 复制代码 这种情况下:
    • foo()被包含在对象内
    • foo()的调用前方有对obj的引用
  • 显式绑定 这是非常直观的绑定方式、 function foo(){ ... } let obj={ a:2 } foo.call(obj); // 2 复制代码 通过call。我们把它的this强行绑定到了obj上,于是输出obj.a; 当然我们知道对应的还有apply函数
    • bind bind函数是另一种强制绑定的解决方案,bind函数的工作原理非常简单,我们甚至可以手搓一个 在这之前我们要知道bind函数接收一个对象,返回一个绑定了this的函数 那么: Function.prototype.bind=function(obj){ return ()=>{ return this.apply(obj,arguments); } } 复制代码 这应该是我能想到的实现 bind 最少代码的形式;
  • new绑定 在js中,并没有所谓的类,JavaScript的new操作符和传统面向对象的new并不一样; 我们用new调用函数就是所谓的构造 使用new来调用函数,会有如下操作:
    1. 创建一个全新的对象
    2. 新对象要执行[[Prototype]]连接
    3. 新对象绑定函数调用的this
    4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象

    function foo(a){ this.a=a; } let bar=new foo(2); console.log(bar.a); // 2 复制代码


不遵从this词法

我们上边说的并无问题,不过如果对于箭头函数,那么this的作用域又不一样

代码语言:javascript
复制
console.log=()=>{};

这样是一个箭头函数,而这样一个箭头函数的this实际上并不存在,箭头函数的this来自于它的上一层作用域

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • prototype和proto的灵活应用
  • javascript中children和childNodes的区别
  • this指向
    • this究竟绑了谁
      • 不遵从this词法
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档