toString() 的運用:推斷數據範例
為了獲得範例字符串,最好直接運用Object.prototype.toString要領。經由過程函數的call要領,能夠在恣意值上挪用這個要領,協助我們推斷這個值的範例。
**Object.prototype.toString.call(value)**
差別數據範例的Object.prototype.toString要領返回值以下。
數值:返回[object Number]。
字符串:返回[object String]。
布爾值:返回[object Boolean]。
undefined:返回[object Undefined]。
null:返回[object Null]。
數組:返回[object Array]。
arguments 對象:返回[object Arguments]。
函數:返回[object Function]。
Error 對象:返回[object Error]。
Date 對象:返回[object Date]。
RegExp 對象:返回[object RegExp]。
其他對象:返回[object Object]。
能夠寫出一個比typeof運算符更正確的範例推斷函數。
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"
new 敕令的道理
運用new敕令時,它背面的函數順次實行下面的步驟。
- 建立一個空對象,作為將要返回的對象實例。
- 將這個空對象的原型,指向組織函數的prototype屬性。
- 將這個空對象賦值給函數內部的this關鍵字。
- 最先實行組織函數內部的代碼。
組織函數內部,this指的是一個新天生的空對象,一切針對this的操縱,都邑發作在這個空對象上。組織函數之所以叫“組織函數”,就是說這個函數的目標,就是操縱一個空對象(即this對象),將其“組織”為須要的模樣。
假如組織函數內部有return語句,而且return背面隨着一個對象,new敕令會返回return語句指定的對象;不然,就會不論return語句,返回this對象。
var Vehicle = function () {
this.price = 1000;
return 1000;
};
(new Vehicle()) === 1000
// false
上面代碼中,組織函數Vehicle的return語句返回一個數值。這時刻,new敕令就會疏忽這個return語句,返回“組織”后的this對象。
假如return語句返回的是一個跟this無關的新對象,new敕令會返回這個新對象,而不是this對象
var Vehicle = function (){
this.price = 1000;
return { price: 2000 };
};
(new Vehicle()).price
// 2000
假如對一般函數(內部沒有this關鍵字的函數)運用new敕令,則會返回一個空對象。
function getMessage() {
return 'this is a message';
}
var msg = new getMessage();
msg // {}
typeof msg // "object"
函數內部能夠運用new.target屬性。假如當前函數是new敕令挪用,new.target指向當前函數,不然為undefined。
function f() {
console.log(new.target === f);
}
f() // false
new f() // true
能夠推斷函數挪用的時刻,是不是運用new敕令。
function f() {
if (!new.target) {
throw new Error('請運用 new 敕令挪用!');
}
// ...
}
f() // Uncaught Error: 請運用 new 敕令挪用!
Object.create() 建立實例對象
偶然拿不到組織函數,只能拿到一個現有的對象。我們願望以這個現有的對象作為模板,天生新的實例對象
var person1 = {
name: '張三',
age: 38,
greeting: function() {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var person2 = Object.create(person1);
person2.name // 張三
person2.greeting() // Hi! I'm 張三.
Object.getPrototypeOf()
要領返回參數對象的原型。這是獵取原型對象的規範要領。
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true
// 空對象的原型是 Object.prototype
Object.getPrototypeOf({}) === Object.prototype // true
// Object.prototype 的原型是 null
Object.getPrototypeOf(Object.prototype) === null // true
// 函數的原型是 Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype // true
object.create要領,用來滿足這類需求。該要領接收一個對象作為參數,然後以它為原型,返回一個實例對象。該實例完整繼續原型對象的屬性。
// 原型對象
var A = {
print: function () {
console.log('hello');
}
};
// 實例對象
var B = Object.create(A);
Object.getPrototypeOf(B) === A // true
B.print() // hello
B.print === A.print // true
//以A對象為原型,天生了B對象。B繼續了A的一切屬性和要領。
三種體式格局天生的新對象是等價的。
var obj1 = Object.create({});
var obj2 = Object.create(Object.prototype);
var obj3 = new Object();
假如想要天生一個不繼續任何屬性(比方沒有toString和valueOf要領)的對象,能夠將Object.create的參數設為null
對象obj的原型是null,它就不具備一些定義在Object.prototype對象上面的屬性,比方valueOf要領。
var obj = Object.create(null);
obj.valueOf()
// TypeError: Object [object Object] has no method 'valueOf'
第二個參數:是一個屬性形貌對象,它所形貌的對象屬性,會添加到實例對象,作為該對象本身的屬性。
實例對象的isPrototypeOf要領,用來推斷該對象是不是為參數對象的原型。
Object.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false
因為Object.prototype處於原型鏈的最頂端,所以對種種實例都返回true,只要直接繼續自null的對象除外。
對象實例的hasOwnProperty要領返回一個布爾值,用於推斷某個屬性定義在對象本身,照樣定義在原型鏈上。
Date.hasOwnProperty('length') // true
Date.hasOwnProperty('toString') // false
對象的拷貝
確保拷貝后的對象,與原對象具有一樣的原型。
確保拷貝后的對象,與原對象具有一樣的實例屬性。
function copyObject(orig) {
return Object.create(
Object.getPrototypeOf(orig),
Object.getOwnPropertyDescriptors(orig)
);
}
//應用 ES2017 才引入規範的Object.getOwnPropertyDescriptors要領