- 通過new運算符執行結果與直接執行函數結果不一樣。new返回了一個對象
- new運算符會根據方法返回值的不同,執行方式是不一樣的
- 然后,new 會改變this的指向。若直接作為函數執行this指向window,使用new運算符后的this指向當前對象
w3c關于Function的說明
用Function類直接創建函數的語法如下:
var function_name = new function(arg1, arg2, ... , argN, function_body)
在上面的形式中,每個arg都是一個參數,最后一個參數是函數本體(要執行的代碼)。這些參數必須是字符串。
function Person() {}
具體的執行就是調用Function()構造函數進行構造的,最后一個參數是函數體。
當執行var person = new Function("name", "console.log(name)")
即創建了一個function實例對象,自帶了Object+Funciton的屬性方法。
在JS中,有兩個基礎原型,分別是Function.prototype和Object.prototype。這兩個原型組成了JS中的所有實例他們的關系是 Function.prototype ----> Object.prototype ----> null
常用的創建類的有兩種方法,我們從這兩種方法講兩種prototype
的關系。
第一種是先有一個原型,直接令新的對象的__proto__
指向已經有的原型。這種時候可以類比繼承關系,但區別是把那個原型的狀態(如屬性的取值等)也一并繼承過來了。
但是記住這個時候新的對象從原型繼承的值如果沒有被初始化/賦值,原型中的值改變的話,新的對象中的對應值也會改變。
第二種是使用new來繼承,new在JS里這樣運行:
- 創建一個最基礎的Object對象(內容為空 )并且初始化。
- 把后面的構造函數放進剛創建的obj中,并且設置
__proto__
為函數的對象。 - 使用創建出的對象作為obj,在obj中執行那個函數,,當然那個函數要對剛創建的這個對象進行初始化,然后返回。
- 如果返回的是Object對象,new就返回這個對象,否則返回剛創建的obj。
這里解釋一下函數的原型類型:
比如說有 function A(){ var a = 1 }
那么A是一個Object,他的constructor就是A(),平時調用A()就相當于調用A這個Object的構造函數。
引申探討prototype和__proto__
prototype屬性是一個指針,指向一個對象,而這個對象的用途是包含可以有特定類型的所有實例共享的屬性和方法。prototype是通過調用構造函數而創建的那個對象實例的原型對象。hasOwnProperty()判斷指定屬性是否為自有屬性;in操作符對原型屬性和自有屬性都返回true。
var obj = {a: 1};
obj.hasOwnProperty("a"); // true
obj.hasOwnProperty("toString"); // false
"a" in obj; // true
"toString" in obj; // true
__proto__是指向本對象的原型對象的指針。可稱為隱式原型,一個對象的隱式原型指向構造該對象的構造函數的原型,這也保證了實例能夠訪問在構造函數原型中定義的屬性和方法。
function Foo(){}
var Boo = {name: "Boo"};
Foo.prototype = Boo;
var f = new Foo();
console.log(f.__proto__ === Foo.prototype); // true
console.log(f.__proto__ === Boo); // true
Object.getPrototypeOf(f) === f.__proto__; // true
示例(結合關系圖食用)
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName: function(){
console.log("my name is " + this.name);
}
}
var p1 = new Person("ligang");
var p2 = new Person("Camile");
p1.sayName(); // my name is ligang
p2.sayName(); // my name is Camile
prototype和__proto__參考