- 通過new運(yùn)算符執(zhí)行結(jié)果與直接執(zhí)行函數(shù)結(jié)果不一樣损合。new返回了一個(gè)對象
- new運(yùn)算符會(huì)根據(jù)方法返回值的不同省艳,執(zhí)行方式是不一樣的
- 然后,new 會(huì)改變this的指向嫁审。若直接作為函數(shù)執(zhí)行this指向window跋炕,使用new運(yùn)算符后的this指向當(dāng)前對象
w3c關(guān)于Function的說明
用Function類直接創(chuàng)建函數(shù)的語法如下:
var function_name = new function(arg1, arg2, ... , argN, function_body)
在上面的形式中,每個(gè)arg都是一個(gè)參數(shù)律适,最后一個(gè)參數(shù)是函數(shù)本體(要執(zhí)行的代碼)辐烂。這些參數(shù)必須是字符串。
function Person() {}
具體的執(zhí)行就是調(diào)用Function()構(gòu)造函數(shù)進(jìn)行構(gòu)造的捂贿,最后一個(gè)參數(shù)是函數(shù)體纠修。
當(dāng)執(zhí)行var person = new Function("name", "console.log(name)")
即創(chuàng)建了一個(gè)function實(shí)例對象,自帶了Object+Funciton的屬性方法厂僧。
在JS中扣草,有兩個(gè)基礎(chǔ)原型,分別是Function.prototype和Object.prototype。這兩個(gè)原型組成了JS中的所有實(shí)例他們的關(guān)系是 Function.prototype ----> Object.prototype ----> null
常用的創(chuàng)建類的有兩種方法辰妙,我們從這兩種方法講兩種prototype
的關(guān)系鹰祸。
第一種是先有一個(gè)原型,直接令新的對象的__proto__
指向已經(jīng)有的原型密浑。這種時(shí)候可以類比繼承關(guān)系蛙婴,但區(qū)別是把那個(gè)原型的狀態(tài)(如屬性的取值等)也一并繼承過來了。
但是記住這個(gè)時(shí)候新的對象從原型繼承的值如果沒有被初始化/賦值尔破,原型中的值改變的話街图,新的對象中的對應(yīng)值也會(huì)改變。
第二種是使用new來繼承呆瞻,new在JS里這樣運(yùn)行:
- 創(chuàng)建一個(gè)最基礎(chǔ)的Object對象(內(nèi)容為空 )并且初始化台夺。
- 把后面的構(gòu)造函數(shù)放進(jìn)剛創(chuàng)建的obj中,并且設(shè)置
__proto__
為函數(shù)的對象痴脾。 - 使用創(chuàng)建出的對象作為obj颤介,在obj中執(zhí)行那個(gè)函數(shù),赞赖,當(dāng)然那個(gè)函數(shù)要對剛創(chuàng)建的這個(gè)對象進(jìn)行初始化滚朵,然后返回。
- 如果返回的是Object對象前域,new就返回這個(gè)對象辕近,否則返回剛創(chuàng)建的obj。
這里解釋一下函數(shù)的原型類型:
比如說有 function A(){ var a = 1 }
那么A是一個(gè)Object匿垄,他的constructor就是A(),平時(shí)調(diào)用A()就相當(dāng)于調(diào)用A這個(gè)Object的構(gòu)造函數(shù)移宅。
引申探討prototype和__proto__
prototype屬性是一個(gè)指針,指向一個(gè)對象椿疗,而這個(gè)對象的用途是包含可以有特定類型的所有實(shí)例共享的屬性和方法漏峰。prototype是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對象實(shí)例的原型對象。hasOwnProperty()判斷指定屬性是否為自有屬性届榄;in操作符對原型屬性和自有屬性都返回true浅乔。
var obj = {a: 1};
obj.hasOwnProperty("a"); // true
obj.hasOwnProperty("toString"); // false
"a" in obj; // true
"toString" in obj; // true
__proto__是指向本對象的原型對象的指針÷撂酰可稱為隱式原型靖苇,一個(gè)對象的隱式原型指向構(gòu)造該對象的構(gòu)造函數(shù)的原型,這也保證了實(shí)例能夠訪問在構(gòu)造函數(shù)原型中定義的屬性和方法班缰。
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
示例(結(jié)合關(guān)系圖食用)
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__參考