我们接着上面一篇继续~javascript
JavaScript中的Date类型使用自UTC时间,1970年1月1日零时开始的毫秒数来保存日期。
建立一个日期对象:java
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()一般有如下几种格式的参数: 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.app
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
var start = Date.now() //获取开始时间 do() //作些啥 var stop = Date.now() //获取结束时间
若是某些浏览器不支持的话,咱们能够经过如下技巧得到当前时间的毫秒数,就是在前面加一个‘+’:函数
var s = +new Date() console.log(s) //1506069877901
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返回的是时间对象的毫秒数。this
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"
以上的这些方法都会根据系统环境而异。prototype
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()
在JavaScript中,函数其实就是一个对象,每一个函数都是Function类型的实例,并且和其余引用类型同样具备属性和方法。
由于函数是一个对象,因此函数名实际上是一个指向函数对象的指针,不会与某个函数绑定。
定义函数有两种方法:函数声明和函数表达式。指针
function fn(){ ... } var fn = function() { ... };
还有一种方法就是经过Function构造函数。Function构造函数能够接受任意数量的参数,但最后一个参数始终都是被当作函数体。前面的额参数则枚举新函数的参数。code
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是不会保存对函数的引用。并且因为第一行已经报错了,代码也不会继续向下执行。
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 } } }
函数内部属性
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引用的是全局对象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的调用位置就是全局做用域
function outer() { inner() } function inner() { console.log(inner.caller) } outer()
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的指向,其他的参数都是直接传递给函数。
--本篇记录不是一次性写完,中间有不少事情耽搁了,零零散散的感受没有什么逻辑,随便看看了各位~