资讯专栏INFORMATION COLUMN

重温JS基础--引用类型(二)

NusterCache / 1395人阅读

摘要:创建一个日期对象中国标准时间在调用构造函数而不传参数的情况下,新创建的对象自动获得当前日期和时间。日期格式化方法类型还有一些专门用于将日期格式化为字符串的方法中国标准时间下午以上的这些方法都会根据系统环境而异。

咱们接着上面一篇继续~

1. Date类型

JavaScript中的Date类型使用自UTC时间,1970年1月1日零时开始的毫秒数来保存日期。
创建一个日期对象:

var now = new Date()
console.log(now) //Fri Sep 22 2017 15:42:29 GMT+0800 (中国标准时间)

在调用Date构造函数而不传参数的情况下,新创建的对象自动获得当前日期和时间

如果想根据特定的日期和时间创建日期对象,必须传入表示日期的毫秒数(即从UTC时间开始截止到当前的毫秒数)。

var d = new Date(2165461213546)
console.log(d) //Sun Aug 15 2038 13:00:13 GMT+0800 (中国标准时间)

Date.parse() 、 Date.UTC()
还有一些简化的方法:Date.parse() 和 Date.UTC()。其中Date.parse()方法接受一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数(但是在JavaScript中并没有规定传入改方法的参数的格式):

Date.parse()通常有以下几种格式的参数:
1."月/年/日", 如:6/12/2017
2."英文月名 日,年",如:January 12,2004
3."英文星期几 英文月名 日 年 时:分:秒 时区",如Tue May 25 2004 00:00:00 GMT-0700

var some = new Date(Date.parse("May 25, 2004"))
console.log(some) //Tue May 25 2004 00:00:00 GMT+0800 (中国标准时间)

//其实这样写也是可以的,它在内部会先调用Date.parse()方法
var someDate = new Date("May 25, 2004"); 

Date.UTC()方法同样也是返回表示日期的毫秒数,它和Date.parse()在构建值时使用不同的信息。Date.UTC()接受的参数分别是年份,基于0的月份,月中的哪一天,小时数,分钟,秒,毫秒。在这些参数中,前两个参数是必填的。如果没有提供月中的日期数,则会默认为1,如果省略其他数,则都假设为0.

var y2k = new Date(Date.UTC(2000, 0))
console.log(y2k) //Sat Jan 01 2000 08:00:00 GMT+0800 (中国标准时间)

//其实这样写也是可以的.
var d = new Date(2000, 0)
var d1 = new Date(2005,4,5,17,55,55)
以上代码创建的日期对象,只不过这次的日期对象是基于系统设置的be

Date.now()
该方法可以获取当前日期和时间的毫秒数:

var start = Date.now() //获取开始时间

do() //做些啥

var stop = Date.now() //获取结束时间

如果某些浏览器不支持的话,我们可以通过以下技巧获得当前时间的毫秒数,就是在前面加一个‘+’

var s = +new Date()
console.log(s) //1506069877901

继承的方法
这里说下继承自Object的三个方法,toLocalString, toString, valueOf

var d = new Date()
d.toLocaleString() //"2017/9/22 下午4:49:43"
d.toString() //"Fri Sep 22 2017 16:49:43 GMT+0800 (中国标准时间)"
d.valueOf() //1506070183078

稍微下他们之间的区别,主要valueOf返回的是时间对象的毫秒数。

日期格式化方法
Date类型还有一些专门用于将日期格式化为字符串的方法:

var d = new Date()
d.toDateString()  //"Fri Sep 22 2017"
d.toTimeString() //"17:02:27 GMT+0800 (中国标准时间)"
d.toLocaleDateString() //"2017/9/22"
d.toLocaleTimeString() //"下午5:02:27"
d.toUTCString() //"Fri, 22 Sep 2017 09:02:27 GMT"

以上的这些方法都会根据系统环境而异。

日期/时间组件方法
下面介绍一下Date对象提供的一些方法,可以取得和设置日期值中特定部分的方法。

var d = new Date()

1. 获取日期的毫秒数,和valueOf方法返回的值相同。
d.getTime() //1506071307006

2. 通过毫秒设置日期,会改变当前的日期对象。
d.setTime(1213123)
console.log(d) //Thu Jan 01 1970 08:20:13 GMT+0800 (中国标准时间)

3. 获取4位数的年份
d.getFullYear() // 1970

4. 返回UTC日期的4位数年份
d.getUTCFullYear() //1970

5. 返回日期中的月份,从0开始算起
d.getMonth() // 8

6. 返回UTC日期中的月份,从0开始算起
d.getUTCMonth() //8

7. 返回日期月份中的天数, 如果传入的值超过了该月应有的天数,则增加月份
d.getDate() // 22

8. 返回UTC日期月份中的天数, 如果传入的值超过了该月应有的天数,则增加月份
d.getUTCDate() // 22

9. 返回日期中星期的星期几(0表示星期天,6表示星期6)
d.getDay() //6

10. 返回UTC中的日期中的星期几(0表示星期天,6表示星期6)
d.getUTCDay() //1

11.返回日期中的小时数(0~23),传入的值超过23则增加月份中的天数
d.getHours() // 9

12. 返回UTC日期中的小时数(0~23),传入的值超过23则增加月份中的天数
d.getUTCHours()

13. 返回日期中的分钟数(0~59),也可以进行设置。
d.getMinutes()

14. 返回UTC中日期的分钟数,也可以进行设置。
d.getUTCMinutes()

15. 返回日期中的秒数0~59,也可以进行设置。
d.getSeconds()

16. 返回日期对象中UTC的秒数
d.getUTCSeconds()

17. 返回日期中的毫秒数,也可以进行设置
d.getMilliseconds()
二. Function类型

在JavaScript中,函数其实就是一个对象,每个函数都是Function类型的实例,而且和其他引用类型一样具有属性和方法。
因为函数是一个对象,所以函数名其实是一个指向函数对象的指针,不会与某个函数绑定
定义函数有两种方法:函数声明和函数表达式。

function fn(){ ... }

var fn = function() { ... };

还有一种方法就是通过Function构造函数。Function构造函数可以接受任意数量的参数,但最后一个参数始终都是被看成函数体。前面的额参数则枚举新函数的参数。

var fn = new Function("num1", "num2", "return num1+num2")

从技术的角度来说,这是一个函数表达式。但是最佳实践中并不推荐使用这种方法,因为这种方法会导致解析两次代码。第一次是正常的解析,第二次是解析传入构造函数中的字符串。
由于函数名是一个指针,所以函数可能会具有多个函数名:

function fn() {console.log(123)}
var fn1 = fn

如果以下操作还可以继续访问:
fn = null
fn1() // 123

没有重载
先看一个例子:

fucntion add (num){
    return num + 100
}

function add (num) {
    return num + 200
}
console.log(add(100)) // 300

然后改写下上面的例子:

var add = function(num) {
    return num + 100
}

add = function (num) {
    return num + 200
}
add(100) //300

函数表达式和函数声明
之前说过创建函数的方法有两种,函数声明和函数表达式,我们来看下他们之间的区别。

js引擎在解析的时候会先读取函数声明,并使其在执行任何代码之前可以访问。因为在代码执行之前,解析器就已经通过一个函数声明提升的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎会在第一遍声明函数,并将它们放到源代码树的顶部。

函数表达式,必须等解析器执行到它所在的代码行,才会真正的被解释执行:

console.log(fn(10, 10)) // error "fn is not a function"

var fn = function(a, b) {
    return a + b
}

以上代码会报错,因为在函数位于一个初始化语句中。而不是一个函数声明。换句话说,在执行到函数所在的语句之前,变量fn是不会保存对函数的引用。而且由于第一行已经报错了,代码也不会继续向下执行。

作为值的函数
JavaScript中,函数名本身也是一个变量,所以函数可以作为值来使用。所以函数可以作为另外一个函数的参数,而且可以将一个函数作为另外一个函数的结果进行返回。

function callSomeFn(fn, arg) {
    return fn(arg)
}

如上,这个函数接受两个参数,第一个参数应该是一个函数,第二个参数是要传递给函数的一个值。然后,就可以如下:

function add(num) {
    return num+10
}
var res = callSomeFn(fn, 10)
console.log(res) //20

function greet (name) {
    return "hello" + name
}
var res = callSomeFn(greet, "world")
console.log(res) //"hello world"

而且,我们可以在一个函数中返回另外一个函数,如下我们通过函数创建另外一个函数然后返回:

function create(proName) {
    return function (obj1, obj2) {
        var val1 = obj1[proName]
        var val2 = obj[proName]
        
        if(val1 < val2) {
            return -1
        }else if(val1 > val2) {
            return 1
        }else {
            return 0
        }
    }
}

函数内部属性

callee
在函数内部,有两个特殊的对象:arguments和this。arguments是一个类数组的对象,它包含传入函数中的所有参数。该对象还有一个callee的属性,该属性是一个指针,指向的是拥有这个arguments对象的函数。

function factor(num) {
    if(num <= 1) {
        return 1
    }else{
        return num * factor(num - 1)
    }
}

如上是一个递归函数,通过callee可以改写成下面这样:

function factor(num) {
    if(num < 1) {
        return 1
    }else{
        return num * argument.callee(num - 1)
    }
}

this
函数内部的另一个特殊对象是thisthis引用的是函数当前执行的环境对象。this是在函数调用的时候进行绑定的。完全取决于函数的调用位置。

当某个函数在全局作用域中定义的,当在全局作用域中调用改函数时,this引用的是全局对象window.

var a = 12
function b() {
    console.log(this.a)
}
b() //12

在理解this的绑定过程之前,我们了解一下调用位置,调用位置表示的是函数所被调用的位置,而不是其声明的位置。

如何知道函数的调用位置,最重要的是分析函数的调用栈(即为了到达当前执行位置所调用的所有函数)。那么调用位置就是当前正在执行函数的前一个调用中。

function baz() {
  //当前的调用栈是baz
  //当前的调用位置是全局作用域,即当前调用栈的前一个调用
  console.log("baz");
  bar();
}

function bar() {
  //当前调用栈是 baz-->bar
  //当前的调用位置是:baz
  console.log("bar");
  foo();
}

function foo() {
  //当前的调用栈是baz --> bar --> foo
  //当前调用位置是bar
}

baz(); //<-- baz的调用位置就是全局作用域

caller
另外一个函数对象的属性是:caller.该属性保存着调用当前函数的函数引用。如果在全局作用域中调用当前函数,它的值为null。

function outer() {
    inner()
}
function inner() {
    console.log(inner.caller)
}
outer()

函数属性和方法
前面说过函数也是一个对象,所以函数也是有属性和方法的。每个函数都包含两个属性:length和prototype.其中length属性表示函数接受命名参数的个数。

funtion setName(name) {
    console.log(name)
}
function sun(s1, s2){
    //...
}
console.log(setName.length) // 1
console.log(sun.length) //2

再说下prototype属性,它是保存所有实例方法的真正所在。

再说下apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。它们是每个函数都具有的非继承而来的方法。
apply()接受两个参数,一个是在其中运行函数的作用域,另一个是参数数组。其中第二个参数可以是Array实例,也可以是arguments对象。
call()和apply()相同,它们的区别仅在于接受参数的方式不同。call()第一个参数是this的指向,其余的参数都是直接传递给函数。

--本篇记录不是一次性写完,中间有很多事情耽搁了,零零散散的感觉没有什么逻辑,随便看看了各位~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88679.html

相关文章

  • 重温基础】22.内存管理

    摘要:内存泄露内存泄露概念在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。判断内存泄漏,以字段为准。 本文是 重温基础 系列文章的第二十二篇。 今日感受:优化学习方法。 系列目录: 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理) 【重温基础】1-14篇 【重温基础】15.JS对象介绍 【重温基础】16.JSON对象介绍 【重温基础】1...

    Pandaaa 评论0 收藏0
  • 重温JS基础--变量、作用域和内存问题

    摘要:作用域链是保证对执行环境有权访问的所有变量和函数的有序访问。如上,包含的作用域链包含它自己的变量对象和全局环境的变量对象,为什么能在函数内访问,这就是通过作用域链找的。 前言JavaScript的变量类型是弱类型的,在特定的时间内保存一个特定的值,变量的值和数据类型可以在脚本的生命周期内随意改变。 1. 基本类型和引用类型的值 JavaScript包含两种不同类型的值:基本类型和引用类...

    huaixiaoz 评论0 收藏0
  • 重温JS基础--引用类型(三)

    摘要:今天把接下来引用类型中的一些内容全部记录完毕基本包装类型为了便于操作基本类型值,还提供了种特殊的引用类型。这三种类型具有与各自的基本类型响应的特殊行为。重写后的返回对象表示的数值类型,另外两个方法则返回字符串形式的数值。 今天把接下来引用类型中的一些内容全部记录完毕~ 基本包装类型 为了便于操作基本类型值,JavaScript还提供了3种特殊的引用类型:Boolean, Number,...

    kel 评论0 收藏0
  • 重温JS基础--继承

    摘要:继承了如上,我们通过方法借调了超类的构造函数,实际上是在新创建的实力环境下调用了构造函数。组合继承组合继承的基本思想将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。继承方法在上面这个例子中,构造函数定义了两个属性和。 在ECMAScript中只支持实现继承,而且实现继承主要是依靠原型链来实现的。 1. 什么是原型链 继承基本思想:利用原型让一个引用类型继承另一个...

    sixleaves 评论0 收藏0
  • 重温基础】19.闭包

    摘要:系列目录复习资料资料整理个人整理重温基础篇重温基础对象介绍重温基础对象介绍重温基础介绍重温基础相等性判断本章节复习的是中的关于闭包,这个小哥哥呀,看看。这里随着闭包函数的结束,执行环境销毁,变量回收。 本文是 重温基础 系列文章的第十九篇。今日感受:将混乱的事情找出之间的联系,也是种能力。 系列目录: 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理) 【重温基础】...

    nanfeiyan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<