前陣子忙于準備CET-6,,沒時間更新文章,之后大概一個月將忙于準備期末考,,也應該不會更新了,,今天趁周末有時間再更新一篇最近研究的一些東西吧,。 callee和callerfunction inner(){ console.log(arguments.callee);//指向擁有這個arguments對象的函數(shù),即inner() console.log(arguments.callee.caller);//這個屬性保存著調(diào)用當前函數(shù)的函數(shù)的引用,即outer() console.log(inner.caller);//[Function: outer] } function outer(){ inner(); } outer();
callee 放回正在執(zhí)行的函數(shù)本身的引用,,它是arguments 的一個屬性
caller 返回一個函數(shù)的引用,,這個函數(shù)調(diào)用了當前的函數(shù)。
嚴格模式下,,不允許訪問arguments.callee 和arguments.caller 屬性,,主要體現(xiàn)在arguments.[[Get]] 內(nèi)部方法 嚴格模式下,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 }();
在使用立即執(zhí)行的函數(shù)表達式時,,可以利用 void 運算符讓 JavaScript 引擎把一個函數(shù)識別成函數(shù)表達式 而不是函數(shù)聲明(語句)。 實參和形參var add = function (a,b) { console.log(arguments.length);//3,表示實參長度 console.log(arguments.callee.length);//2,,表示形參長度 }; add(1,2,3);
Array.prototype.slice.call(arguments)slice 有兩個用法,,一個是String.slice ,一個是Array.slice ,,第一個返回的是字符串,,第二個返回的是數(shù)組。
Array.prototype.slice.call(arguments) 能夠?qū)?code style='background:#f6f6f6 ;color:#c7254e;padding:2px 4px;'>arguments轉(zhuǎn)成數(shù)組,,那么就是arguments.toArray().slice() ;
因為arguments 并不是真正的數(shù)組對象,,只是與數(shù)組類似而已,所以它并沒有slice 這個方法,,而Array.prototype.slice.call(arguments) 可以理解成是將arguments 轉(zhuǎn)換成一個數(shù)組對象,,讓arguments 具有slice() 方法。 比如: var arr = [1,2,3,4]; console.log(Array.prototype.slice.call(arr,2));//[3,4]
同樣,,還有Array.prototype.forEach.call() ,,forEach() 方法讓數(shù)組的每一項都執(zhí)行一次給定的函數(shù)。 String()我們可以用String() 來確定某一變量是否是null 或者undefined var a , b = null; String(a);//undefined String(b);//null
直接調(diào)用String() 作為方法時,,將會執(zhí)行類型轉(zhuǎn)換,,返回經(jīng)過toString(value) 得到的字符串字面量(與new String() 不同),或者空字符串(''). window 對象 <script> (function () { var root = this; console.log(root);//即window對象 })(); </script>
打開控制臺,,你可以看到window 對象的一系列屬性和方法: new functionvar 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);
js中的false和true//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 ,空字符串'' ,,數(shù)字0和NaN 以外,,其他所有值都被當做是真,包括true ,,字符串'' 里包含的值,,以及所有對象。 valueOf() 和 toString()valueOf() 和toString() 方法是所有ECMAScript 對象擁有的內(nèi)置方法,。操作對象時,,valueOf() 和toString() 會被隱式的調(diào)用。
//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() 方法的目的是將對象轉(zhuǎn)換成最有意義的原始值([[PrimitiveValue]] ),。即ECMAScript 的5種基本類型中的三種,,布爾值、數(shù)字,、字符串 ,。
當valueOf 方法被調(diào)用時,會調(diào)用內(nèi)置的ToObject ,,并將this 作為參數(shù)傳進去,。ToObject 檢測會根據(jù)參數(shù)類型進行數(shù)值的轉(zhuǎn)換: Undefined - 拋出TypeError異常 Null - 拋出TypeError異常 Boolean - 創(chuàng)建一個Boolean對象,調(diào)用ToBoolean生成[[PrimitiveValue]] Number - 創(chuàng)建一個Number對象,,調(diào)用ToNumber生成[[PrimitiveValue]] String - 創(chuàng)建一個String對象,,調(diào)用ToString生成[[PrimitiveValue]] Object - 對象本身
ECMAScript 對象的大多數(shù)操作的轉(zhuǎn)換結(jié)果是字符串,這兩個方法的結(jié)果是相同的,。但是如果操作的對象為Number ,、Boolean 或者Date ,結(jié)果就不同了,。
var foo = { toString: function () { return 'foo'; }, valueOf: function () { return 5; } }; console.log(foo + 'bar'); // 5bar console.log([foo, 'bar'].join('')); // foobar
在這個上下文環(huán)境中,,我們使用'+' 操作符來使字符串連接,但是,,foo 并沒有使用toString 來轉(zhuǎn)換成字符串,,它使用valueOf 轉(zhuǎn)換成一個number ,這并不是我們想要的,, 但它是如何工作的,,這是+ 運算符的算術和字符串連接超載的副作用。'+' 操作符有一個明確的處理過程: 1.評估左手側(cè),,并得到該值,。 2.評估右手側(cè),并獲得該值。 3.同時在左手和右手側(cè)調(diào)用ToPrimitive(無提示) 4.如果任何原始值是一個字符串,,然后跳到7,。 5.在這兩個值調(diào)用ToNumber。 6.返回值的總和,。 7.在這兩個值調(diào)用toString,。 8.返回的值連接起來
setInterval和setTimeoutalert(1); setTimeout('alert(2)', 0); alert(3);
執(zhí)行順序為:1,3,,2,,雖然延時了0ms setTimeout 0 //正常情況下javascript都是按照順序執(zhí)行的。但是我們可能讓該語句 后面的語句執(zhí)行完再執(zhí)行本身,,這時就可以用到setTimeout延時0ms來實現(xiàn)了。
cookie的創(chuàng)建和刪除cookie 可以跨越一個域名下的多個網(wǎng)頁,,但不能跨越多個域名使用,。
document.cookie = “user = 值;expires = 過期時間;path = 路徑訪問; domain = 域名訪問;secure = 安全的https限制通信'
cookie的創(chuàng)建方式設置cookie 我們一般都封裝成一個函數(shù): 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()漢字轉(zhuǎn)成unicode編碼,toGMTString() 把日期對象轉(zhuǎn)成字符串 }
刪除cookie為了刪除一個cookie ,可以將其過期時間設定為一個過去的時間,,例如: //獲取當前時間 var date=new Date(); //將date設置為過去的時間 date.setTime(date.getTime()-10000); //將userId這個cookie刪除 document.cookie='userId=828; expires='+date.toGMTString();
給cookie設置終止日期到現(xiàn)在為止,所有的cookie 都是單會話cookie ,,即瀏覽器關閉后這些cookie 將會丟失,事實上這些cookie 僅僅是存儲在內(nèi)存中,,而沒有建立相應的硬盤文件。 在實際開發(fā)中,,cookie 常常需要長期保存,例如保存用戶登錄的狀態(tài),。這可以用下面的選項來實現(xiàn): document.cookie='userId=828; expiress=GMT_String';
其中GMT_String 是以GMT 格式表示的時間字符串,這條語句就是將userId 這個cookie 設置為GMT_String 表示的過期時間,,超過這個時間,cookie 將消失,,不可訪問,。例如:如果要將cookie 設置為10天后過期,,可以這樣實現(xiàn): <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>
對象和函數(shù)可以如數(shù)組一樣,,用屬性名或方法名作為下標來訪問: 對象的創(chuàng)建//對象的創(chuàng)建 function MyFunc(){} var obj1 = new MyFunc();//使用new操作符,借助MyFun函數(shù),,就創(chuàng)建了一個對象 var obj2 = new MyFunc;//函數(shù)也可以沒有括號,,但仍將調(diào)用該函數(shù)
可以把上面的代碼改寫成這種等價形式: function MyFunc(){}; var obj1 = {};//創(chuàng)建一個對象 MyFunc.call(obj1);//將obj1對象作為this指針調(diào)用MyFunc函數(shù)
作用域通過自執(zhí)行的匿名函數(shù)你可以把所有原本屬于全局的變量都隱藏起來: //創(chuàng)建一個新的匿名函數(shù),,作為包裝 (function () { //變量原本應該是全局的 var msg = 'Thanks for visiting'; window.onunload = function () { console.log(msg); }; })();
上下文對象是通過this 變量體現(xiàn)的,,這個變量永遠指向當前代碼所處的對象中,。 var obj = { yes : function(){ //this == obj this.val = true; }, no : function(){ this.val = false; } }; console.log(obj.val == null);//true //執(zhí)行了yes函數(shù)后,將val屬性與'obj'對象關聯(lián)起來 obj.yes(); console.log(obj.val == true);//true
String 原型方法的擴展 //公共正則表達式處理函數(shù) 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,''); };
^ 表示字符串必須以后面的規(guī)則開頭,,而(^\s*) 表示的就是以0個空格或者多個空格開頭,,后面的(\s*$) 的意思就是, 以0個空格或者多個空格結(jié)尾。
//判斷輸入內(nèi)容是否為空 String.prototype.isNull = function(){ return this.trim().length == 0 ? true : false; } //判斷輸入的字符是否為英文字母\數(shù)字\下劃線 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); }
constructor屬性function User(){} var me = new User(); console.log(me.constructor);//[Function: User] //用前一個對象的Constructor引用來創(chuàng)建一個新的User對象 var you = new me.constructor(); console.log(me.constructor == you.constructor);//true
Object.createfunction 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]
“數(shù)據(jù)屬性”是可獲取且可設置值的屬性,。 數(shù)據(jù)屬性描述符包含 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會成為所創(chuàng)建對象的數(shù)據(jù)屬性 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 = {}; // 以字面量方式創(chuàng)建的空對象就相當于: foo = Object.create(Object.prototype);
另外: console.log(Object.prototype);//{} console.log(Object.create(Object.prototype));//{}
通過Object.create(Object.prototype) 創(chuàng)建的實例對象就繼承了Object 原型下的屬性和方法。 javascript 所有function 類型的對象都有一個prototype 屬性,。這個prototype 屬性本身又是一個object 類型的對象,,原型對象都包含一個指向構造函數(shù)的指針,而每一個實例也都包含一個指向原型對象內(nèi)部的指針,。
參考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Glob...
prototypefunction User(){} var u1 = new User(); console.log(u1.prototype);//使用對象實例無法訪問到prototype console.log(User.prototype);//{},使用構造函數(shù)名訪問prototype console.log(u1.__proto__);//{},使用對象實例訪問prototype的指針 //使用字面量的方式創(chuàng)建原型對象,,這里{}就是對象 User.prototype = { name : 'trigkit4', age : 22 };
使用構造函數(shù) 創(chuàng)建原型對象和使用字面量 創(chuàng)建對象在使用上基本相同,但還是有些區(qū)別,,字面量創(chuàng)建的方式使用constructor 屬性不會指向?qū)嵗?,而會指?code style='background:#f6f6f6 ;color:#c7254e;padding:2px 4px;'>Object,構造函數(shù)創(chuàng)建的方式則相反 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指向?qū)嵗龑ο?,可以這么做: User.prototype = { constructor : User; }
字面量方式為什么constructor 會指向Object ,?因為User.prototype = {}; 這種寫法其實就是創(chuàng)建了一個新對象: 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] })();
Object.prototype.toString在toString() 方法被調(diào)用時,會執(zhí)行下面的操作步驟: 如果this的值為undefined,則返回'[object Undefined]'. 如果this的值為null,則返回'[object Null]'. 讓O成為調(diào)用ToObject(this)的結(jié)果. 讓class成為O的內(nèi)部屬性[[Class]]的值. 返回三個字符串'[object ', class, 以及 ']'連接后的新字符串.
由于 JavaScript 中一切都是對象,任何都不例外,,對所有值類型應用Object.prototype.toString.call() 方法結(jié)果如下: 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 中,想要判斷某個對象值屬于哪種內(nèi)置類型,最靠譜的做法就是通過Object.prototype.toString 方法.
面向?qū)ο?/h2>下面是來自Prototype.js 的一段代碼: //創(chuàng)建一個名為'Class'的全局對象 var Class = { //它只有一個函數(shù),其作用是創(chuàng)建一個新的對象構造函數(shù) create: function(){ //創(chuàng)建一個匿名的對象構造函數(shù) return function () { //調(diào)用它本身的初始化方法 this.initialize.apply(this,arguments); } } }; //給Object對象添加一個新的靜態(tài)方法,,它的作用是把屬性從一個對象復制到另一個中 Object.extend = function (destination,source) { //遍歷所有要擴展的屬性 for(property in source){ //然后將他們添加到目標對象中 destination[property] = source[property]; } };
成員操作符function aFunc(){}//或者var aFunc = function(){}; aFunc.oProperty = '函數(shù)的一個屬性'; aFunc.aMethod = function(){ console.log('函數(shù)的一個方法'); }; console.log(aFunc['oProperty']);//將函數(shù)當成數(shù)組以屬性名作為下標來訪問屬性 console.log(aFunc['aMethod']());//將函數(shù)當數(shù)組以方法名作為下標來調(diào)用方法 //遍歷函數(shù)的所有屬性和方法 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 = ''; }; //靜態(tài)屬性 Constructor.name = 'trigkit4'; //靜態(tài)方法 Constructor.alertName = function (name) { console.log(this.name); };
特權方法 是指在構造函數(shù)的作用域中使用this 關鍵字定義的方法,;與私有方法不同,特權方法能夠被公開訪問,,而且還能夠訪問私有成員,。
由于私有和特權成員在函數(shù)的內(nèi)部,因此它們會被帶到函數(shù)的每個實例中,。 公有的原型成員是對象藍圖的一部分,,適用于通過new 關鍵字實例化的該對象的每個實例 靜態(tài)成員只適用于對象的一個特殊實例
使用對象字面量語法來向prototype 屬性添加所有公有成員: function Constructor(){ //私有和特權成員 } //公有方法 Constructor.prototype = { propertyA: 'value1', propertyB: 'value2', methodA: function(){}, methodB: function(){} };
刪除不要的節(jié)點DOM 元素在瀏覽器中所占用的空間是非常大的,要及時回收不用的節(jié)點:
var node = parentNode.removeChild(node); node = null;//設置為空,,釋放空間 CollectGarbage();//IE,回收資源
后續(xù)更新
|