面向?qū)ο缶幊蹋琽op并不是針對(duì)與javascript,很多語(yǔ)言都實(shí)現(xiàn)了oop這樣一個(gè)編程發(fā)法論,比如說(shuō)java,c++,都是實(shí)現(xiàn)了oop的語(yǔ)言。
概念與繼承
概念
面向?qū)ο蟪绦蛟O(shè)計(jì)(Object-oriented programming OOP)是一種程序設(shè)計(jì)范型,同時(shí)也是一種程序開發(fā)的方法。對(duì)象指的是類的實(shí)例,它將對(duì)象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性,靈活性和擴(kuò)展性。 來(lái)自于 ----維基百科
OOP重點(diǎn)的一些特性:
繼承
封裝
多態(tài)
抽象
基于原型的繼承
function Foo() {
this.y = 2;
};
Foo.prototype.x = 1;
console.log(Foo.prototype); //object
var obj1 = new Foo();
console.log(obj1.y); //2
console.log(obj1.x); //1
函數(shù)聲明創(chuàng)建Foo()
函數(shù),這個(gè)函數(shù)就會(huì)有一個(gè)內(nèi)置的Foo.prototype
,并且這個(gè)屬性是對(duì)象,并且是預(yù)設(shè)的。
function Foo() {
this.y = 2;
};
console.log(Foo.prototype); //object
function Foo() {
this.y = 2;
};
Foo.prototype.x = 1;
console.log(Foo.prototype); //object
然后我們把Foo.prototype
對(duì)象增加一個(gè)屬性x
并且賦值為1。
function Foo() {
this.y = 2;
};
Foo.prototype.x = 1;
console.log(Foo.prototype); //object
var obj1 = new Foo();
console.log(obj1.y); //2
console.log(obj1.x); //1
然后使用new
操作符new Foo();
來(lái)創(chuàng)建一個(gè)Foo();
的實(shí)例,叫obj1,
當(dāng)時(shí)用new
去調(diào)用函數(shù)的時(shí)候,那么構(gòu)造器也就是說(shuō)這樣一個(gè)函數(shù)就會(huì)作為一個(gè)構(gòu)造器來(lái)使用,并且this會(huì)指向一個(gè)對(duì)象,而對(duì)象的原型會(huì)指向構(gòu)造器的Foo.prototype
屬性。obj1實(shí)際上會(huì)成為Foo構(gòu)造器中的this,最后會(huì)作為返回值,并且在構(gòu)造器里面調(diào)用的時(shí)候會(huì)把y賦值為2,并且obj1的原型,也就是他的proto會(huì)指向Foo.prototype內(nèi)置屬性,最后可以看到obj.y會(huì)返回2,obj.x會(huì)返回1,y是這個(gè)對(duì)象上的直接量,而x是原型鏈上的,也就是Foo.prototype的
function Foo() {
this.y = 2;
};
Foo.prototype.x = 1;
console.log(Foo.prototype);
var obj1 = new Foo();
console.log(obj1);
prototype屬性與原型
function Foo() {};
console.log(Foo.prototype);
Foo.prototype.x=1;
var obj=new Foo();
使用函數(shù)聲明去中創(chuàng)建一個(gè)函數(shù)的時(shí)候,這個(gè)函數(shù)就會(huì)有一個(gè)prototype
屬性,并且他默認(rèn)會(huì)有兩個(gè)屬性。
一個(gè)是
constructor:Foo
constructor屬性會(huì)指向它本身Foo。另外一個(gè)屬性是
__proto__
,__proto__
是Foo.prototype
的原型,那么他的原型會(huì)指向Object.prototype
也就是說(shuō)一般的對(duì)象比如用花括號(hào)括起來(lái)的對(duì)象字面量,他也會(huì)有__proto__
他會(huì)指向Object.prototype
因此Object.prototype
上面的一些方法比如說(shuō)toString
,valueOf
才會(huì)被每一個(gè)一般的對(duì)象所使用,
x:1
這個(gè)是我通過(guò)賦值語(yǔ)句增加的。
**這句是Foo.prototype的結(jié)構(gòu) **
也就是說(shuō),這里面有一個(gè)Foo
函數(shù),這個(gè)Foo
函數(shù)呢會(huì)有一個(gè)prototype
的對(duì)象屬性,他的作用呢就是在當(dāng)使用new Foo()
去構(gòu)造Foo的實(shí)例的時(shí)候,那么構(gòu)造器的prototype
的屬性,會(huì)用作new
出來(lái)的這些對(duì)象的原型。
所以要搞清楚prototype
和原型是兩回事。
prototype
是函數(shù)對(duì)象上的預(yù)設(shè)的對(duì)象屬性,而原型呢是我們對(duì)象上的一個(gè)原型,原型通常都是他的構(gòu)造器的prototype
屬性。
實(shí)現(xiàn)class繼承另外一個(gè)class
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.legs_num = 2;
Person.prototype.arms_num = 2;
Person.prototype.walk = function() {
console.log(this.name + "is walking...");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new,and form" + this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
console.log(Student.prototype);
var t = new Student("黃繼鵬", 23, "class2");
t.hi();
console.log(t.legs_num);
t.walk();
t.learn('math')
這里有一個(gè)函數(shù)Person,人的意思意思是說(shuō)只要人類的class。 在這個(gè)構(gòu)造函數(shù)里面,通過(guò)this.name = name;
和this.age = age;
去做一個(gè)賦值,如何Person作為函數(shù)直接去調(diào)用的話,那么這里的this會(huì)指向全局對(duì)象,在瀏覽器里就會(huì)指向window,使用new去調(diào)用Person函數(shù)的時(shí)候,this會(huì)指向一個(gè)原型為Person.prototype的一個(gè)空對(duì)象,然后通過(guò)this.name去給這個(gè)空對(duì)象賦值,最后這里沒有寫返回值,使用new會(huì)this會(huì)作為返回值。
通過(guò)Person.prototype.hi
來(lái)創(chuàng)建所有Person實(shí)例共享的方法。
再創(chuàng)建Student函數(shù),學(xué)生這樣一個(gè)class,那么學(xué)生是也是人,他是可以繼承人的,每一個(gè)學(xué)生也是人,并且學(xué)生會(huì)有他的班級(jí)名稱或者一些其他的功能方法,
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
創(chuàng)建Student函數(shù),這里多傳了一個(gè)className參數(shù),在Student函數(shù)也算是子類里先調(diào)用下父類,Person.call(this, name, age);然后把this作為Person里面的this再把name和age傳進(jìn)去,注意這里的this在new被實(shí)例的時(shí)候會(huì)是這個(gè)實(shí)例的返回值也就是直接量,
this.className = className;
并且把Student的實(shí)例做好賦值,
把Student.prototype能繼承Person.prototype的一些方法
Student.prototype = Object.create(Person.prototype);
使用這樣一個(gè)方法去拿到Person.prototype
對(duì)象作為原型的值,這樣Student.prototype
原型就會(huì)有Person.prototype
的值了。
如果去掉Object.create()
的話。人有一些方法,但是學(xué)生也有自己的一些方法,Student.prototype = Person.prototype;
,Person.prototype;
賦值給Student.prototype
的時(shí)候,當(dāng)我想增加學(xué)生自己的方法時(shí),比如說(shuō)
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
這樣的話由于他們指向的是同一個(gè)對(duì)象,給Student.prototype
增加對(duì)象的時(shí)候同時(shí)也給Person.prototype;
增加了同樣的屬性,這不是我們想要的。
所以說(shuō)通過(guò)Student.prototype = Object.create(Person.prototype);
創(chuàng)建了一個(gè)空的對(duì)象,而這個(gè)空對(duì)象的原型指向了Person.prototype
這樣的話我們既可以在訪問Student.prototype
的時(shí)候,可以向上查找Person.prototype
同時(shí)可以在不影響Person.prototype
的前提下創(chuàng)建一些自己的Student.prototype
上的方法。
Student.prototype.constructor = Student;
每一個(gè)prototype
屬性對(duì)象都會(huì)有一個(gè)constructor
屬性,他的值是指向函數(shù)本身,實(shí)際上這里面沒有太大的用處,因?yàn)槲覀兛梢匀我獾娜バ薷模菫榱吮WC一致性,我們把這個(gè)改成Student.prototype.constructor = Student;
面向?qū)ο罄訙y(cè)試
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.legs_num = 2;
Person.prototype.arms_num = 2;
Person.prototype.walk = function() {
console.log(this.name + "is walking...");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new,and form" + this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
var t = new Student("黃繼鵬", 23, "class2");
var poi=new Person("李漢",22);
console.log(poi);
console.log(t);
再談原型鏈
再談原型鏈
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.legs_num = 2;
Person.prototype.arms_num = 2;
Person.prototype.walk = function() {
console.log(this.name + "is walking...");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new,and form" + this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
console.log(Student.prototype);
var peng = new Student("黃繼鵬", 23, "class2");
peng.hi();
console.log(peng.legs_num);
peng.walk();
peng.learn('math')
這個(gè)圖里面說(shuō)明了上面代碼例子的示意圖
通過(guò)var peng = new Student("黃繼鵬", 23, "class2");
來(lái)創(chuàng)建了一個(gè)實(shí)例peng
。
peng
的實(shí)例他的原型我們用__proto__
表示,就會(huì)指向構(gòu)造器Student.prototype
的屬性。
Student.prototype
上面有hi
和learn
方法,Student.prototype
是通過(guò)Student.prototype = Object.create(Person.prototype);
構(gòu)造的,所以說(shuō)Student.prototype
是一個(gè)對(duì)象,并且的原型指向Person.prototype
。
Person.prototype
。也給她設(shè)置了很多屬性,hi
...等。
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.hi
其實(shí)是內(nèi)置的普通對(duì)象,內(nèi)置對(duì)象他本身也會(huì)有他的原型,他的原型就是Object.prototype
。
也就是因?yàn)檫@樣所以說(shuō)隨便一個(gè)對(duì)象才會(huì)有hasOwnProperty
,valueOf
,toString
等一些公共的函數(shù),這些函數(shù)都是從Object.prototype
而來(lái)的。
當(dāng)我們?nèi)フ{(diào)用
peng.hi();
方法的時(shí)候,首先看這個(gè)對(duì)象上本身有沒有hi
方法,在本身沒有所以會(huì)像上查找,差遭到peng
原型也就是Student.prototype
有這樣一個(gè)函數(shù)方法,所以最終調(diào)用的是Student.prototype
上面的hi
方法。
如果Student.prototype
不去寫hi
方法的時(shí)候peng.hi();
會(huì)去調(diào)用Person.prototype.hi
這樣一個(gè)方法,
當(dāng)我們調(diào)用peng.walk();
的時(shí)候,先找peng
上發(fā)現(xiàn)沒有,然后Student.prototype
上面,也沒有,Person.prototype
有walk
所以最終調(diào)用結(jié)果是Person.prototype
上面的walk
方法。
那么我想去調(diào)用peng.toString
的時(shí)候也是一層一層向上查找。找到Object.prototype
那么最后到null
也就是最根源沒有了。
關(guān)于一切的一般對(duì)象都會(huì)指向Object.prototype
做一個(gè)實(shí)際的實(shí)驗(yàn)
var obj={x:1,y:2}
比如用obj
等于一個(gè)花括號(hào)空的字面量,給他屬性。
那么我們知道obj
就是一個(gè)普通的對(duì)象,obj.x就為1
,
可以通過(guò)obj.__proto__
這樣的機(jī)制可以讓你去訪問對(duì)象的原型
除了obj.__proto__
以外,在es5里面提供了一個(gè)方法能夠返回一個(gè)對(duì)象的原型,就是Object.getPrototypeOf(obj)
這樣一個(gè)方法,可以返回對(duì)象原型,
通過(guò)三個(gè)等號(hào)來(lái)判斷Object.getPrototypeOf(obj)
是不是等于Object.prototype
返回true
也就是說(shuō)我們隨便一個(gè)對(duì)象仔面了也好或者是函數(shù)函數(shù)內(nèi)置的prototype
屬性然后去判斷 他的原型可以看到也是Object.prototype
也正因?yàn)槿绱怂哉f(shuō)我們才可以調(diào)用obj.toString()
,obj.valueOf()
實(shí)際上這些方法都是取自Object.prototype
上的,
并不是所有對(duì)象最終原型鏈上最終都有Object.prototype
比如說(shuō)我們創(chuàng)建obj2對(duì)象,然后用var obj2=Object.create(null)
,obj2.create(null)
的作用是創(chuàng)建空對(duì)象,并且這個(gè)對(duì)象的原型指向這樣一個(gè)參數(shù),但是這里參數(shù)是null,obj2這個(gè)時(shí)候他的原型就是undefined
,obj2.toString
就是undefined
那么通過(guò)Object.create(null)
創(chuàng)建出來(lái)的對(duì)象,就沒有Object.prototype
的一些方法。所以說(shuō)并不是所有的對(duì)象都繼承Object.prototype
只是一般我們對(duì)象字面量或者是函數(shù)的prototype
預(yù)制的一般的對(duì)象上都有Object.prototype
并不是所有的函數(shù)對(duì)象都有prototype這樣一個(gè)預(yù)制屬性的
function abc() {};
console.log(abc.prototype);
var hh = abc.bind(null);
console.log(hh.prototype);
使用es5友誼和bind
函數(shù),bind
函數(shù)是用來(lái)修改函數(shù)在運(yùn)行時(shí)的this
的,bind
函數(shù)返回的也是一個(gè)函數(shù),但是bind
函數(shù)就沒有prototype
預(yù)設(shè)屬性。
prototype屬性
javascript中的prototype
原型,不像java的class,是一旦寫好了以后不太容易去動(dòng)態(tài)改變的,但是javascript中原型實(shí)際上也是普通的對(duì)象,那么意味著在程序運(yùn)行的階段我們也可以動(dòng)態(tài)的給prototype
添加或者刪除一些屬性,
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.legs_num = 2;
Person.prototype.arms_num = 2;
Person.prototype.walk = function() {
console.log(this.name + "is walking...");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new,and form" + this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
console.log(Student.prototype);
var peng = new Student("黃繼鵬", 23, "class2");
peng.hi();
console.log(peng.legs_num);
peng.walk();
peng.learn('math')
Student.prototype.x=101;
console.log(peng.x);//101
Student.prototype={y:2};
console.log(peng.y);//undefined
console.log(peng.x);//101
var nunnly=new Student("nunnly", 23, "class3");
console.log(nunnly.y);//2
console.log(nunnly.x);//undefined
Student.prototype.x=101;
console.log(peng.x);//101
Student.prototype={y:2};
console.log(peng.y);//undefined
console.log(peng.x);//101
var nunnly=new Student("nunnly", 23, "class3");
console.log(nunnly.y);//2
console.log(nunnly.x);//undefined
比如說(shuō)這里的Student.prototype
同過(guò)Student.prototype.x=101;
把huang
的原型動(dòng)態(tài)的添加一個(gè)屬性x
那么我們發(fā)現(xiàn)所有的實(shí)例都會(huì)受到影響,現(xiàn)在去調(diào)用console.log(peng.x);
發(fā)現(xiàn)他賦值為101了,
直接修改Student.prototype={y:2};構(gòu)造器的屬性,把他賦值為一個(gè)新的對(duì)象,y:2
。
有趣的現(xiàn)象
console.log(peng.y);//undefined
console.log(peng.x);//101
當(dāng)我們?nèi)バ薷?code>Student.prototype的時(shí)候并不能修改已經(jīng)實(shí)例化的對(duì)象,也就是說(shuō)已經(jīng)實(shí)例化的peng
他的原型已經(jīng)指向當(dāng)時(shí)的Student.prototype
如果你修改了Student.prototype
的話,并不會(huì)影響已經(jīng)創(chuàng)建的實(shí)例,之所以修改的x沒有問題,是因?yàn)槲覀冃薷牡氖?code>peng原型的那個(gè)對(duì)象,
但是再去用new重新實(shí)例化對(duì)象,那么會(huì)發(fā)現(xiàn)x不見了,并且y是新的y值。
內(nèi)置構(gòu)造器的prototype
Object.prototype.x = 1;
var obj = {
y: 3
};
console.log(obj.x); //1
for (var key in obj) {
console.log(key + "=" + obj[key]); //y=3 x=1
}
比如說(shuō)我們想讓所有的對(duì)象他的原型鏈上都會(huì)有x屬性會(huì)發(fā)現(xiàn)所有對(duì)象都會(huì)有x屬性,這樣的設(shè)置會(huì)在for...in的時(shí)候會(huì)被枚舉出來(lái),那么怎么解決這個(gè)問題呢
Object.defineProperty(Object.prototype, 'x', {writable: true,value: 1});
var obj = {
y: 3
};
console.log(obj.x); //1
for (var key in obj) {
console.log(key + "=" + obj[key]); //y=3
}
- value:屬性的值給屬性賦值
- writable:如果為false,屬性的值就不能被重寫。
- get: 一旦目標(biāo)屬性被訪問就會(huì)調(diào)回此方法,并將此方法的運(yùn)算結(jié)果返回用戶。
- set:一旦目標(biāo)屬性被賦值,就會(huì)調(diào)回此方法。
- configurable:如果為false,則任何嘗試刪除目標(biāo)屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無(wú)效化。
- enumerable:是否能在for...in循環(huán)中遍歷出來(lái)或在Object.keys中列舉出來(lái)。
創(chuàng)建對(duì)象-new/原型鏈
function foo(){} //定義函數(shù)對(duì)象 foo
foo.prototype.z = 3; //函數(shù)對(duì)象默認(rèn)帶foo.prototype對(duì)象屬性 這個(gè)對(duì)象會(huì)作為new實(shí)例的對(duì)象原型 對(duì)象添加z屬性=3
var obj =new foo(); //用構(gòu)造器方式構(gòu)造新的對(duì)象
obj.y = 2; //通過(guò)賦值添加2個(gè)屬性給obj
obj.x = 1; //通過(guò)new去構(gòu)造這樣一個(gè)對(duì)象他的主要特點(diǎn)是,他的原型會(huì)指向構(gòu)造器的foo.prototype屬性
//一般foo.prototype對(duì)象他的原型又會(huì)指向Object.prototype
//Object.prototype他也會(huì)有他的原型最后指向null整個(gè)原型鏈的末端
obj.x; // 1 //訪問obj.x發(fā)現(xiàn)對(duì)象上有x返回1
obj.y; // 2 //訪問obj.y發(fā)現(xiàn)對(duì)象上有x返回2
obj.z; // 3 //obj上沒有z并不會(huì)停止查找,會(huì)去查找他的原型foo.prototype.z返回3
typeof obj.toString; // ‘function' 這是一個(gè)函數(shù),toString是Object.prototype上面的每個(gè)對(duì)象都有
'z' in obj; // true obj.z是從foo.prototype繼承而來(lái)的,所以說(shuō)obj里面有z
obj.hasOwnProperty('z'); // false 表示z并不是obj直接對(duì)象上的,而是對(duì)象原型鏈上的。
instanceof
instanceof
instanceof
數(shù)據(jù)類型判斷方法
console.log([1, 2] instanceof Array); //true
console.log(new Object() instanceof Array); //false
左邊要求是一個(gè)對(duì)象instanceof
右邊要求是一個(gè)函數(shù)或者說(shuō)構(gòu)造器
他會(huì)判斷右邊的構(gòu)造器的 prototype
的屬性是否出現(xiàn)在左邊這個(gè)對(duì)象的原型鏈上。
console.log([1, 2] instanceof Array); //true
[1,2]
這里是數(shù)組字面量,數(shù)組的字面量他也有他的原型,他的原型就是Array.prototype
所以返回true
。
console.log(new Object() instanceof Array); //false
new Object()
new一個(gè)空對(duì)象空對(duì)象的原型會(huì)指向Object.prototype
。new Object()
的原型鏈不是Array.prototype
所以返回false
需要注意的是
console.log([1, 2] instanceof Object); //true
因?yàn)閿?shù)組他的原型是Array.prototype,而Array.prototype的原型就是Object.prototype,所以返回true
所以說(shuō)instanceof我們可以判斷某一個(gè)對(duì)象他的原型鏈上是否有右邊這個(gè)函數(shù)構(gòu)造器的prototype對(duì)象屬性。
function per() {};
function sor() {};
sor.prototype = new per();
sor.prototype.constructor = sor;
var peng = new sor();
var han = new per();
console.log(peng instanceof sor); //true
console.log(peng instanceof per); //true
console.log(han instanceof sor); //false
console.log(han instanceof per); //true
實(shí)現(xiàn)繼承的方式
實(shí)現(xiàn)繼承的方式
if (!Object.create) {
Object.create = function(proto) {
function F() {};
F.prototype = proto;
return new F();
};
}
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new");
};
Person.prototype.legs_num = 2;
Person.prototype.arms_num = 2;
Person.prototype.walk = function() {
console.log(this.name + "is walking...");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
};
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.hi = function() {
console.log('Hi my name is' + this.name + ",I'm" + this.age + "years old new,and form" + this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + 'is learing' + subject + 'at' + this.className + '.');
};
console.log(Student.prototype);
var t = new Student("黃繼鵬", 23, "class2");
t.hi();
console.log(t.legs_num);
t.walk();
t.learn('math');
Object.create()
也有他的問題,他是es5之后才支持的,但是沒有關(guān)系在es5之前我們可以寫一個(gè)模擬的方法。
if (!Object.create) {
Object.create = function(proto) {
function F() {};
F.prototype = proto;
return new F();
};
}
這里面我們可以判斷下有沒有Object.create
如果沒有的話,我們可以把他賦值為一個(gè)函數(shù),這里會(huì)傳進(jìn)來(lái)一個(gè)參數(shù),寫一個(gè)臨時(shí)的空函數(shù),把空函數(shù)的prototype屬性賦值給想要作為原型的對(duì)象,然后返回new F(),會(huì)創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象的原型指向構(gòu)造器的prototype,利用這樣的規(guī)則返回空對(duì)象,并且對(duì)象原型指向參數(shù)也就是要繼承的原型。