前陣子忙於準備CET-6,沒時間更新文章,以後大概一個月將忙於準備期末考,也應該不會更新了,今天趁週末有時間再更新一篇最近研究的一些東西吧。javascript
function inner(){ console.log(arguments.callee);//指向擁有這個arguments對象的函數,即inner() console.log(arguments.callee.caller);//這個屬性保存着調用當前函數的函數的引用,即outer() console.log(inner.caller);//[Function: outer] } function outer(){ inner(); } outer();
callee
放回正在執行的函數自己的引用,它是arguments
的一個屬性caller
返回一個函數的引用,這個函數調用了當前的函數。java
嚴格模式下,不容許訪問arguments.callee
和arguments.caller
屬性,主要體如今arguments.[[Get]]
內部方法node
嚴格模式下,arguments,arguments.callee,arguments.caller,arguments.callee.caller
也不容許再被賦值。以下代碼所示:正則表達式
'use strict'; // 兩次都是1 void function fn(a) { console.log(arguments[0]); a = 2; console.log(arguments[0]); }(1); //function(){}(); 會運行錯誤, 以下能夠正確被運行. void function(){ console.log('hi');//hi }();
在使用當即執行的函數表達式時,能夠利用 void
運算符讓 JavaScript
引擎把一個函數識別成函數表達式
而不是函數聲明(語句)。數組
var add = function (a,b) { console.log(arguments.length);//3,表示實參長度 console.log(arguments.callee.length);//2,表示形參長度 }; add(1,2,3);
slice
有兩個用法,一個是String.slice
,一個是Array.slice
,第一個返回的是字符串,第二個返回的是數組。瀏覽器
Array.prototype.slice.call(arguments)
可以將arguments
轉成數組,那麼就是arguments.toArray().slice()
;安全
由於arguments
並非真正的數組對象,只是與數組相似而已,因此它並無slice
這個方法,而Array.prototype.slice.call(arguments)
能夠理解成是將arguments
轉換成一個數組對象,讓arguments
具備slice()
方法。 好比:cookie
var arr = [1,2,3,4]; console.log(Array.prototype.slice.call(arr,2));//[3,4]
一樣,還有Array.prototype.forEach.call()
,forEach()
方法讓數組的每一項都執行一次給定的函數。app
咱們能夠用String()
來肯定某一變量是不是null
或者undefined
dom
var a , b = null; String(a);//undefined String(b);//null
直接調用String()
做爲方法時,將會執行類型轉換,返回通過toString(value)
獲得的字符串字面量(與new String()
不一樣),或者空字符串('').
<script> (function () { var root = this; console.log(root);//即window對象 })(); </script>
打開控制檯,你能夠看到window
對象的一系列屬性和方法:
var a = function () {}; console.log(typeof a);//function var b = new function () {}; console.log(typeof b);//object var c = new Function (); console.log(typeof c);//function
new function
是一個JavaScript
中用戶自定義的對象
var obj = function (name) { this.name = name; }; var b = new obj('trigkit4'); console.log(b.name);
//false console.log(Boolean(''));//false console.log(Boolean(null));//false console.log(Boolean(undefined));//false console.log(Boolean(0));//false console.log(Boolean(false));//false console.log(Boolean(NaN));//false //true console.log(Boolean(' '));//true console.log(Boolean('NaN'));//true
除了false,null,undefined
,空字符串''
,數字0和NaN
之外,其餘全部值都被當作是真,包括true
,字符串""
裏包含的值,以及全部對象。
valueOf()
和toString()
方法是全部ECMAScript
對象擁有的內置方法。操做對象時,valueOf()
和toString()
會被隱式的調用。
//valueOf() console.log(Object.valueOf());//[Function: Object] console.log(Object.prototype.valueOf());//{} var boo = new Boolean(1); console.log(boo.valueOf());//true var bar = Boolean(0); console.log(bar.valueOf());//false var str = String("trigkit4"); console.log(str.valueOf());//trigkit4 console.log(null.valueOf());//TypeError console.log(undefined.valueOf());//TypeError //toString() console.log(Object.prototype.toString());//[object Object] console.log(Object.toString());//function Object() { [native code] } Object.prototype.toString.call(null);//[object Null] Object.prototype.toString.call(undefined);//[object Undefined] {a: 'b'}.toString();//[object Object]
valueOf()
方法的目的是將對象轉換成最有意義的原始值([[PrimitiveValue]]
)。即ECMAScript
的5種基本類型中的三種,布爾值、數字、字符串
。
當valueOf
方法被調用時,會調用內置的ToObject
,並將this
做爲參數傳進去。ToObject
檢測會根據參數類型進行數值的轉換:
Undefined - 拋出TypeError異常 Null - 拋出TypeError異常 Boolean - 建立一個Boolean對象,調用ToBoolean生成[[PrimitiveValue]] Number - 建立一個Number對象,調用ToNumber生成[[PrimitiveValue]] String - 建立一個String對象,調用ToString生成[[PrimitiveValue]] Object - 對象自己
ECMAScript
對象的大多數操做的轉換結果是字符串,這兩個方法的結果是相同的。可是若是操做的對象爲Number
、Boolean
或者Date
,結果就不一樣了。
var foo = { toString: function () { return "foo"; }, valueOf: function () { return 5; } }; console.log(foo + "bar"); // 5bar console.log([foo, "bar"].join("")); // foobar
在這個上下文環境中,咱們使用"+"
操做符來使字符串鏈接,可是,foo
並無使用toString
來轉換成字符串,它使用valueOf
轉換成一個number
,這並非咱們想要的,
但它是如何工做的,這是+
運算符的算術和字符串鏈接超載的反作用。"+"
操做符有一個明確的處理過程:
1.評估左手側,並獲得該值。 2.評估右手側,並得到該值。 3.同時在左手和右手側調用ToPrimitive(無提示) 4.若是任何原始值是一個字符串,而後跳到7。 5.在這兩個值調用ToNumber。 6.返回值的總和。 7.在這兩個值調用toString。 8.返回的值鏈接起來
alert(1); setTimeout("alert(2)", 0); alert(3);
執行順序爲:1,3,2,雖然延時了0ms
setTimeout 0 //正常狀況下javascript都是按照順序執行的。可是咱們可能讓該語句 後面的語句執行完再執行自己,這時就能夠用到setTimeout延時0ms來實現了。
cookie
能夠跨越一個域名下的多個網頁,但不能跨越多個域名使用。
document.cookie = 「user = 值;expires = 過時時間;path = 路徑訪問; domain = 域名訪問;secure = 安全的https限制通訊"
設置cookie
咱們通常都封裝成一個函數:
function addCookie(sName,sValue,day) { var expireDate = new Date(); expireDate.setDate(expireDate.getDate()+day);; //設置失效時間 document.cookie = escape(sName) + '=' + escape(sValue) +'; expires=' + expireDate.toGMTString();6 //escape()漢字轉成unicode編碼,toGMTString() 把日期對象轉成字符串 }
爲了刪除一個cookie
,能夠將其過時時間設定爲一個過去的時間,例如:
//獲取當前時間 var date=new Date(); //將date設置爲過去的時間 date.setTime(date.getTime()-10000); //將userId這個cookie刪除 document.cookie="userId=828; expires="+date.toGMTString();
到如今爲止,全部的cookie
都是單會話cookie
,即瀏覽器關閉後這些cookie
將會丟失,事實上這些cookie
僅僅是存儲在內存中,而沒有創建相應的硬盤文件。
在實際開發中,cookie
經常須要長期保存,例如保存用戶登陸的狀態。這能夠用下面的選項來實現:
document.cookie="userId=828; expiress=GMT_String";
其中GMT_String
是以GMT
格式表示的時間字符串,這條語句就是將userId
這個cookie
設置爲GMT_String
表示的過時時間,超過這個時間,cookie
將消失,不可訪問。例如:若是要將cookie
設置爲10天后過時,能夠這樣實現:
<script language="JavaScript" type="text/javascript"> //獲取當前時間 var date=new Date(); var expiresDays=10; //將date設置爲10天之後的時間 date.setTime(date.getTime()+expiresDays*24*3600*1000); //將userId和userName兩個cookie設置爲10天后過時 document.cookie="userId=828; userName=hulk; expires="+date.toGMTString(); </script>
對象和函數能夠如數組同樣,用屬性名或方法名做爲下標來訪問:
//對象的建立 function MyFunc(){} var obj1 = new MyFunc();//使用new操做符,藉助MyFun函數,就建立了一個對象 var obj2 = new MyFunc;//函數也能夠沒有括號,但仍將調用該函數
能夠把上面的代碼改寫成這種等價形式:
function MyFunc(){}; var obj1 = {};//建立一個對象 MyFunc.call(obj1);//將obj1對象做爲this指針調用MyFunc函數
經過自執行的匿名函數你能夠把全部本來屬於全局的變量都隱藏起來:
//建立一個新的匿名函數,做爲包裝 (function () { //變量本來應該是全局的 var msg = "Thanks for visiting"; window.onunload = function () { console.log(msg); }; })();
上下文對象是經過this
變量體現的,這個變量永遠指向當前代碼所處的對象中。
var obj = { yes : function(){ //this == obj this.val = true; }, no : function(){ this.val = false; } }; console.log(obj.val == null);//true //執行了yes函數後,將val屬性與'obj'對象關聯起來 obj.yes(); console.log(obj.val == true);//true
//公共正則表達式處理函數 String.prototype.Regular = function(reg){ var result = true; if(this.length > 0){ if(!reg.test(this)){ result = false; } } return result; } //.trim()方法 String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g,''); };
^
表示字符串必須之後面的規則開頭,而(^\s*)
表示的就是以0個空格或者多個空格開頭,後面的(\s*$)
的意思就是, 以0個空格或者多個空格結尾。
//判斷輸入內容是否爲空 String.prototype.isNull = function(){ return this.trim().length == 0 ? true : false; } //判斷輸入的字符是否爲英文字母\數字\下劃線 String.prototype.isVersion = function(){ var reg = /^([a-zA-Z_])([a-zA-Z0-9_.])*$/; return this.Regular(reg); } // 判斷輸入的字符串,不包括單引號 String.prototype.isString = function(){ var reg = /^[^']*$/; return this.Regular(reg); } //判斷輸入的字符是否爲英文字母 String.prototype.isLetter = function(){ var reg = /^[a-zA-Z]+$/; return this.Regular(reg); }
function User(){} var me = new User(); console.log(me.constructor);//[Function: User] //用前一個對象的Constructor引用來建立一個新的User對象 var you = new me.constructor(); console.log(me.constructor == you.constructor);//true
function Parent(){} var o = Object.create(Parent.prototype); console.log(o instanceof Parent);//true console.log(o instanceof Object);//true console.log(Object.prototype.toString.call(o));//[object Object]
「數據屬性」是可獲取且可設置值的屬性。 數據屬性描述符包含 value
特性,以及 writable、enumerable
和 configurable
特性。 若是未指定最後三個特性,則它們默認爲 false
。
function Parent(){} var o = Object.create(Parent); console.log(o instanceof Parent);//false console.log(o instanceof Object);//true
另一個實例
var book1 = { title:"JS高級程序設計", pages : 1001, getTitle:function(){ console.log(this.title); } }; var book2 = Object.create(book1,{ //title會成爲所建立對象的數據屬性 title:{ configurable:true, enumerable:true, value:"JS權威指南", wratable:true } }); book1.getTitle(); //"JS高級程序設計" book2.getTitle(); //"JS權威指南" console.log(book1.hasOwnProperty("getTitle")); //true console.log('pages' in book2); //true console.log(book2.hasOwnProperty("getTitle")); //false console.log(book1.isPrototypeOf(book2));//true
再看另外一個例子:
function Constructor(){} obj = new Constructor(); // 上面的一句就至關於: obj = Object.create(Constructor.prototype); console.log(obj);//{} console.log(Object.create(Constructor.prototype));//{} console.log(obj instanceof Constructor);//true console.log(Constructor.prototype.isPrototypeOf(obj));//true var foo; foo = {}; // 以字面量方式建立的空對象就至關於: foo = Object.create(Object.prototype);
另外:
console.log(Object.prototype);//{} console.log(Object.create(Object.prototype));//{}
經過Object.create(Object.prototype)
建立的實例對象就繼承了Object
原型下的屬性和方法。
javascript
全部function
類型的對象都有一個prototype
屬性。這個prototype
屬性自己又是一個object
類型的對象,原型對象都包含一個指向構造函數的指針,而每個實例也都包含一個指向原型對象內部的指針。
參考: https://developer.mozilla.org...
function User(){} var u1 = new User(); console.log(u1.prototype);//使用對象實例沒法訪問到prototype console.log(User.prototype);//{},使用構造函數名訪問prototype console.log(u1.__proto__);//{},使用對象實例訪問prototype的指針 //使用字面量的方式建立原型對象,這裏{}就是對象 User.prototype = { name : "trigkit4", age : 22 };
使用構造函數
建立原型對象和使用字面量
建立對象在使用上基本相同,但仍是有些區別,字面量建立的方式使用constructor
屬性不會指向實例,而會指向Object
,構造函數建立的方式則相反
function User(){} User.prototype = { name : "trigkit4", age : 22 }; var u1 = new User(); console.log(u1.constructor);//function Object() {[native code]} console.log(u1 instanceof User);//true console.log(u1.constructor == User);//false console.log(u1.constructor == Object);//true //若是想讓字面量方式的constructor指向實例對象,能夠這麼作: User.prototype = { constructor : User; }
字面量方式爲何constructor
會指向Object
?由於User.prototype = {};
這種寫法其實就是建立了一個新對象:
function User(){} User.prototype = { constructor : User }; var u1 = new User(); console.log(User.constructor);//[Function: Function] console.log(u1.constructor == User);//true
另外一個例子:
(function () { console.log(Object.prototype);//{} console.log(Array.prototype);//[] console.log(Array.prototype.push);//[Function: push] console.log(Function.prototype);//[Function: Empty] console.log(Function.prototype.bind);//[Function: bind] })();
在toString()
方法被調用時,會執行下面的操做步驟:
若是this的值爲undefined,則返回"[object Undefined]". 若是this的值爲null,則返回"[object Null]". 讓O成爲調用ToObject(this)的結果. 讓class成爲O的內部屬性[[Class]]的值. 返回三個字符串"[object ", class, 以及 "]"鏈接後的新字符串.
因爲 JavaScript
中一切都是對象,任何都不例外,對全部值類型應用Object.prototype.toString.call()
方法結果以下:
console.log(Object.prototype.toString.call(123)) //[object Number] console.log(Object.prototype.toString.call('123')) //[object String] console.log(Object.prototype.toString.call(undefined)) //[object Undefined] console.log(Object.prototype.toString.call(true)) //[object Boolean] console.log(Object.prototype.toString.call({})) //[object Object] console.log(Object.prototype.toString.call([])) //[object Array] console.log(Object.prototype.toString.call(function(){})) //[object Function]
全部類型都會獲得不一樣的字符串,幾乎完美。
在JavaScript
中,想要判斷某個對象值屬於哪一種內置類型,最靠譜的作法就是經過Object.prototype.toString
方法.
下面是來自Prototype.js
的一段代碼:
//建立一個名爲"Class"的全局對象 var Class = { //它只有一個函數,其做用是建立一個新的對象構造函數 create: function(){ //建立一個匿名的對象構造函數 return function () { //調用它自己的初始化方法 this.initialize.apply(this,arguments); } } }; //給Object對象添加一個新的靜態方法,它的做用是把屬性從一個對象複製到另外一箇中 Object.extend = function (destination,source) { //遍歷全部要擴展的屬性 for(property in source){ //而後將他們添加到目標對象中 destination[property] = source[property]; } };
function aFunc(){}//或者var aFunc = function(){}; aFunc.oProperty = "函數的一個屬性"; aFunc.aMethod = function(){ console.log("函數的一個方法"); }; console.log(aFunc["oProperty"]);//將函數當成數組以屬性名做爲下標來訪問屬性 console.log(aFunc["aMethod"]());//將函數當數組以方法名做爲下標來調用方法 //遍歷函數的全部屬性和方法 for(var s in aFunc){ console.log(s + "is a "+typeof(aFunc[s])); }
function Constructor(msg){ this.Message = msg; //私有屬性 var separator = '-'; var owner = this; //私有方法 function alertMessage(){ console.log(owner.Message); } alertMessage(); //特權方法(也是公有方法) this.aptMessage = function (str) { this.Message += separator + str; alertMessage(); } } //公有方法 Constructor.prototype.clearMessage = function (str) { this.Message = ''; }; //靜態屬性 Constructor.name = 'trigkit4'; //靜態方法 Constructor.alertName = function (name) { console.log(this.name); };
特權方法
是指在構造函數的做用域中使用this
關鍵字定義的方法;與私有方法不一樣,特權方法可以被公開訪問,並且還可以訪問私有成員。
因爲私有和特權成員在函數的內部,所以它們會被帶到函數的每一個實例中。
公有的原型成員是對象藍圖的一部分,適用於經過new
關鍵字實例化的該對象的每一個實例 靜態成員只適用於對象的一個特殊實例
使用對象字面量語法來向prototype
屬性添加全部公有成員:
function Constructor(){ //私有和特權成員 } //公有方法 Constructor.prototype = { propertyA: 'value1', propertyB: 'value2', methodA: function(){}, methodB: function(){} };
DOM
元素在瀏覽器中所佔用的空間是很是大的,要及時回收不用的節點:
var node = parentNode.removeChild(node); node = null;//設置爲空,釋放空間 CollectGarbage();//IE,回收資源