var Dog = { name : 'dog', speak : function () { alert('Woof!'); } }; var dog = Object.create(Dog); dog.speak();
這裏就是使用了這個方法建立了Dog的一個實例dog,這種方式的本質其實仍是與咱們以前討論的使用空對象掛接原型對象是同樣的,代碼基本就像這樣:編程
Object.create = function (o) { function F() {} F.prototype = o; return new F(); };
使用這種方式較之使用構造函數加new的方式來講更加簡潔,可是不能設置私有和公開成員,並且實例成員在各個實例之間不共享,因此也有必定的侷限性。數組
Object.create(prototype, descriptors) 參數 prototype:必需。 要用做原型的對象。 能夠爲 null,通常也能夠在須要的時候使用getPrototypeOf方法獲取。 descriptors: 可選。 定義的一組屬性的對象字面量,該對象包含了每一個屬性的描述對象。 屬性描述對象稱爲屬性的attributes對象,其含有以下成員: value:表示該屬性的值,默認爲undefined。 writable:表示該屬性的值(value)是否能夠改變,默認爲true。這個值若是是false的話,即便是繼承的子類的話,也沒法修改屬性的值,這個也是講得通的。 enumerable: 表示該屬性是否可枚舉,默認爲true,也就是該屬性會出如今for...in和Object.keys()等操做中。 configurable:表示「可配置性」,默認爲true。若是設爲false,表示沒法刪除該屬性,也不得改變attributes對象(value屬性除外),也就是configurable屬性控制了attributes對象自己的可寫性。 get:表示該屬性的取值函數(getter),默認爲undefined。 set:表示該屬性的存值函數(setter),默認爲undefined。 返回值 一個具備指定的內部原型且包含指定的屬性(若是有)的新對象。
毫無疑問,這個函數最有意義的應該就是第二個參數:一組屬性描述對象,這個在別的語言中很是有用的特性姍姍來遲,雖然在JavaScript中能夠直接使用dog.age=2這種方式定義和修改屬性,可是這種數據成員終究不知足封裝性的需求,並且不知足屬性本質上是函數這種慣例,在這個版本中知足封裝性的屬性(本質上是函數)終於出如今你們視野中了,咱們看一個例子來了解一下如何定義一組屬性:瀏覽器
var Shape = { twoDimensional: true, color: 'Red'}; var Square = Object.create(Shape, { // 簡單的屬性,不包含任何的其餘邏輯的屬性 type: { value: 'square', enumerable: true, writable: true }, // 複雜一點的屬性,包含有一些邏輯的屬性 size: { get: function() { return this.__size__;}, set: function(pSize) { if (pSize > 10) alert('Too large...'); // 其餘的處理邏輯,例如簡單的保存一下 this.__size__ = pSize; }, enumerable: true } }); var square = Object.create(Square); square.type = 'rectangle'; alert(square.type); square.size = 9; alert(square.size);
使用起來仍是很簡單的,可是有一點不太優雅的代碼就是this.__size__這個保存屬性值的成員,爲了知足封裝性,咱們得使用一下閉包的特性了:閉包
var Square = Object.create(Shape, (function () { var m_size; return { // 簡單的屬性,不包含任何的其餘邏輯的屬性 type: { value: 'square', enumerable: true, writable: true }, // 複雜一點的屬性,包含有一些邏輯的屬性 size: { get: function() { return m_size;}, set: function(pSize) { // 常見的條件檢查 if (pSize > 10) alert('Too large...'); // 其餘的處理邏輯,例如簡單的保存一下 m_size = pSize; }, enumerable: true } }; }()));
把Square定義的那段代碼換成上面這段,就有點樣子了。app
var Shape = { twoDimensional: true, color: 'Red'}; var square = Object.create(Shape); Object.defineProperty(square, 'type', { value : 'square', enumerable : true, writable: true }); square.type = 'rectangle'; alert(square.type);
使用defineProperties方法就與create中的第二個參數一致了,參見:函數式編程
var Shape = { twoDimensional: true, color: 'Red'}; var square = Object.create(Shape); Object.defineProperties(square, (function () { var m_size; return { // 簡單的屬性,不包含任何的其餘邏輯的屬性 type: { value: 'square', enumerable: true, writable: true }, // 複雜一點的屬性,包含有一些邏輯的屬性 size: { get: function() { return m_size;}, set: function(pSize) { // 常見的條件檢查 if (pSize > 10) alert('Too large...'); // 其餘的處理邏輯,例如簡單的保存一下 m_size = pSize; }, enumerable: true } }; }())); square.type = 'rectangle'; alert(square.type); square.size = 9; alert(square.size);
注意defineProperty/defineProperties這兩個函數的返回值就是修改後的對象,有時候會使用這個返回值。函數
var Shape = { get type() { return this.__type__;}, set type(value) { this.__type__ = value;} }; var square = Object.create(Shape); square.type = 'rectangle'; alert(square.type);
簡單吧,很簡潔,很是強大。測試
var o = { name: 'frank'}; Object.defineProperties(o, { p1: { value: 1, enumerable: true }, p2: { value: 2, enumerable: false } }); alert(Object.keys(o)); alert(Object.getOwnPropertyNames(o));
注意name這種原始的屬性是可枚舉的,之前經過for/in結合hasOwnProperty方法才能完成枚舉對象自身定義的屬性的功能如今直接能夠經過遍歷keys完成了。this
preventExtensions方法禁止對象添加新屬性,isExtensible檢測對象是否使用了preventExtensions方法。
seal方法禁止對象添加新屬性和禁止刪除已有屬性,isSealed檢測對象是否使用了seal方法。
freeze方法禁止對對象作任何修改,不能添加新屬性和刪除已有屬性,也不能修改對象的屬性值,isFrozen檢測對象是否使用了freeze方法。
看到了吧,一個比一個嚴格,等到了使用freeze方法的時候,對象徹底變成了只讀對象,這個在不少場合下仍是頗有用的。看個簡單的例子:spa
var o = { name: 'frank'}; Object.preventExtensions(o); o.age = 10; alert(o.age); //undefined,表明沒法添加新屬性 Object.seal(o); delete o.name; alert(o.name); // 刪除不了 Object.freeze(o); o.name = 'dong'; alert(o.name); // 沒法修改
var a = ['a','b','c','b']; alert(a.indexOf('b')); // 1 alert(a.indexOf('y')); // -1 alert(a.lastIndexOf('b')); // 3
2. every/some/forEach/filter/map/reduce/reduceRight
[1, 2, 3].map(function(item, index, arr){ return item * item; }); // [1, 4, 9]
經過函數的call方法,map方法能夠用於字符串。
[].map.call('abc', function (x) { return x.toUpperCase() }) // [ 'A', 'B', 'C' ] // 或者 'abc'.split('').map(function (x) { return x.toUpperCase() }) // [ 'A', 'B', 'C' ]
forEach方法對全部元素依次執行一個函數,它與map的區別在於不返回新數組,而是對原數組的成員執行某種操做,甚至可能改變原數組的值。
[1, 2, 3].forEach(function(item, index, arr){ console.log("array[" + index + "] = " + item); }); // array[0] = 1 // array[1] = 2 // array[2] = 3
從上面代碼能夠看到,map和forEach的參數格式是同樣的,都是一個函數。該函數接受三個參數,分別是當前元素、當前元素的位置(從0開始)、整個數組。
var out = []; [1, 2, 3].map(function(item, index, arr){ this.push(item * item); }, out); out // [1, 4, 9]
上面代碼表示,若是提供一個數組做爲第二個參數,則函數內部的this關鍵字就指向這個數組。
[1,2,3,4,5].filter(function(item){ return (item>3); }) // [4,5]
上面代碼將大於3的原數組成員,做爲一個新數組返回。
[1, 2, 3, 4, 5].filter(function(item, index, arr){ return index % 2 === 0; }); // [1, 3, 5]
上面代碼返回原數組偶數位置的成員組成的新數組。
[1, 2, 3, 4, 5].some(function(item, index, arr){ return item >= 3; }); // 返回true
上面代碼表示,若是存在大於等於3的數組成員,就返回true。
[1, 2, 3, 4, 5].every(function(item, index, arr){ return item >= 3; }); // 返回false
上面代碼表示,只有全部數組成員大於等於3,才返回true。
用來累計的變量(即當前狀態)
數組的當前元素
當前元素在數組中的序號(從0開始)
原數組
這四個參數之中,只有前兩個是必須的,後兩個則是可選的。
[1, 2, 3, 4, 5].reduce(function(x, y){ return x+y; }); // 15
上面代碼的參數x表示累計變量,默認爲0,y則是數組的當前元素。reduce方法依次將每一個數組元素加入x,最終返回它們的總和15。
Array.prototype.sum = function (){ return this.reduce(function (partial, value){ return partial + value; }) }; [3,4,5,6,10].sum() // 28
若是要對累計變量指定初值,能夠把它放在reduce方法的第二個參數。
[1, 2, 3, 4, 5].reduce(function(x, y){ return x+y; }, 10); // 25
上面代碼指定參數x的初值爲10,因此數組元素從10開始累加,最終結果爲25。
function findLongest(entries) { return entries.reduce(function (longest, entry) { return entry.length > longest.length ? entry : longest; }, ''); }
var names = ['Collis', 'Cyan']; Array.isArray(names); // true
// 僅僅綁定了this,還須要主動的經過對象去調用 tooltip.show = showText.bind(tooltip); tooltip.show(); overlay.show = showText.bind(overlay); overlay.show(); // 直接調用的apply/call形式 showText.call(tooltip); showText.call(overlay);
Date.now() // 1364026285194相似的數字
若是須要更精確的時間,可使用window.performance.now()。它提供頁面加載到命令運行時的已通過去的時間,單位是浮點數形式的毫秒。
window.performance.now() // 21311140.415相似的數字
這一組方法可用於生成一種惟一的id標識。
alert(new Date().toJSON());
" hello world ".trim() // "hello world"