本文主要跟大家分享JavaScript中的原型與原型鏈詳解,說原型的時候,通常都是在說原型屬性prototype。 <br>
一.介紹
1.函數的prototype屬性
#*所有的函數都有一個prototype屬性,它預設指向一個object空物件(即稱為原型物件)
*原型物件中有一個屬性constructor,它指向函數物件
2.原型物件有什麼作用? ----->為原型物件新增屬性(一般都是新增方法)
*作用:函數的所有實例物件自動擁有原型中的屬性(方法)
//*所有的函数都有一个prototype属性,它默认指向一个object空对象(即称为原型对象) console.log(Date.prototype)//系统内置的,如Date函数 //输出的是object {} 里面有很多属性与方法,这些是后来增加的, function Fn () { } console.log(Fn.prototype)//这是我们自定义的函数 有constructor //*原型对象中有一个属性constructor,它指向函数对象 console.log(Fn.prototype.constructor===Fn); //输出的函数 Fn.prototype.constructor是引用变量 Fn也是引用变量 Fn.prototype.test=function (){ console.log('test()') } Fn.prototype.test();//可以这样用,但是一般不是这样 //一般都是先实例化,然后调用函数 var fn=new Fn(); fn.test();
3 .明確原型與隱式原型
*所有的函數function 都有一個prototype屬性,即為顯式原型
*所有的實例物件都有一個__proto__,可稱為隱式原型
*物件的隱式原型的值為其對應建構子的明確原型的值
3.1 明確原型與隱式原型問題
( 1).prototype屬性是什麼時候加上,它的值是多少?
在定義函數(函數物件被創建)時,Js 引擎自動添加的。預設值是一個空的object實例物件<br>
(注意:定義函數時,內部執行:Fn.prototype={} Fn.prototype.constructor===Fn)
(2).__proto__屬性是什麼時候加上,它的值是多少?
在建立實例物件時,Js 引擎會自動新增的。值為建構子的prototype屬性值
(注意:定義函數時,內部執行:this.__proto__=Fn.prototype(是new出來的實例化物件))<br>
# 3.2總結
a.函數的prototype屬性:在定義函數(函數物件被建立)時,Js 引擎自動加入的,預設值是一個空object物件
b.物件的_ _proto__屬性:建立實例物件時,Js 引擎自動加入的,預設值為建構子的prototype屬性值
c.程式設計師能直接操作明確原型,但不能直接操作隱式原型(es6之前)
function Fn() {//内部执行Fn.prototype={} Fn.prototype.constructor===Fn // body... } //每个函数function 都有一个prototype属性,即为显式原型 console.log(Fn.prototype) //每个实例对象都有一个__proto__,可称为隐式原型 var fn=new Fn();//内部执行:this.__proto__=Fn.prototype(是new出来的实例化对象) console.log(fn.__proto__) //对象的隐式原型的值为其对应构造函数的显式原型的值 console.log(Fn.prototype===fn.__proto__);//true
4.原型鏈
4.1別名,隱式原型鏈(因為是沿著隱式原型找到的)<br>
4.2原型鏈其實是訪問(或是查找)一個物件的屬性時一個流程,
*先在自身屬性中查找,找到返回
*如果沒有,再沿著__proto__這條鏈向上查找,找到返回
*如果最終沒找到,返回underfined
4.3作用是:查找物件的屬性(方法)
<br>
分析:{}是一個new Object的實例化對象,所以就延伸到Object=0x345這邊去(有一個Object的函數,就是建立Object函數物件)
4.4總結:
*每個物件都有tostring()方法<br> *fn.test3值為undefined。 undefined當函數使用,會錯誤<br> *函數物件有顯示原型屬性,實例化物件有隱含原型屬性<br> *方法化的關係
//构造函数function Person(n){this.name = n;} //构造函数对应原型对象Person.prototype.sayHi = function(){alert("大家好,我是" + this.name);} //实例var p1 = new Person("张三");
a.①建構子和實例之間的關係:
實例透過new 關鍵字呼叫建構函式被創造。
如:var dog1 = new Dog();<br>②建構子 與 原型物件物件之間的關係:<br>原型對象,可以透過 建構函式名稱.prototype 取得。 <br>原型物件中的 constructor 屬性會指向建構子。 <br> Dog.prototype;<br> <br><br>③實例和原型物件之間的關係:<br>實例物件中的 __proto__ 屬性會指向 原型物件。 <br><br><br>
<br>b.建構函數,原型,實例物件的關係圖
<br>(1)
#(2)
console.log(Object.prototype)//Object {} console.log(Object.__proto__)//function () {} console.log(Object.__proto__===Date.__proto__)//true console.log(Function.prototype===Function.__proto__)//true console.log(Object.prototype===Object.__proto__)//false<br>總結:
##*實例物件的隱含原型等於建構子的明確原型<br>*任何函式都是Function 的實例,包含Function是它本身的實例化,但不包含實例化物件(如var b=new fn(),其中b就不是Function的實例)
*透過物件.xxx查找屬性時,它是引著隱式原型鏈(__proto__)的原型鏈去找,一直找到Object的原型物件的隱式原型(__proto__=null)<br>
1.实例就是通过构造函数创建的。实例一创造出来就具有constructor属性(指向构造函数)和__proto__属性(指向原型对象),<br>2.构造函数中有一个prototype属性,这个属性是一个指针,指向它的原型对象。<br>3.原型对象内部也有一个指针(constructor属性)指向构造函数:Person.prototype.constructor = Person;<br>4.实例可以访问原型对象上定义的属性和方法。
5.属性问题
给对象属性赋值,是不会查找原型链的
function Person(name,age) { this.name=name; this.age=age; } Person.prototype.setName=function(name){ this.name=name; } Person.prototype.sex='男'; //首先来看 name,age都是自身函数有,sex是原型链上的 var p1=new Person('Tom','12'); p1.setName('jack'); console.log(p1.name,p1.age,p1.sex);//jack 12 男 p1.sex='女';//给对象属性赋值,是不会查找原型链的 console.log(p1.name,p1.age,p1.sex);//jack 12 女 var p2=new Person('Bob','21'); console.log(p2.name,p2.age,p2.sex);//jack 12 男
6.instanceof探索
6.1instanceof是如何判断的?
表达式:A(看着实例) instanceof B(看着构造函数)
如果B函数的显示原型对象在A对象的原型链上,返回true,否则返回false
<br>
function Foo() { } var f1=new Foo(); console.log(f1 instanceof Foo);//true console.log(f1 instanceof Object);//true console.log(Object instanceof Foo);//false console.log(Object instanceof Function);//true console.log(Object instanceof Object);//true console.log(Function instanceof Object);//true console.log(Function instanceof Function);//true
<br><br>
<br>
6.2Function是通过new自己产生的实例
7.题目
/* *查找对象属性是查找对象的原型链,查找原型链是根据隐式原型链 *隐式原型是由实例决定的 */ var A=function(){ } A.prototype.n=1; var b=new A(); A.prototype={//显示原型 n:2,//给显示原型重新赋值,只会影响后面创建的对象 m:3, } //A.prototype.m=5; //给原型对象添加属性,对前后创建对象都有影响 console.log(b.n,b.m,c.n,c.m);//1 5 1 5 var c=new A(); console.log(b.n,b.m,c.n,c.m);//1 undefined 2 3 //题目2 var F=function(){} Object.prototype.a=function(){ console.log('a()') } Function.prototype.a=function(){ console.log('a()') } var f=new F(); f.a();//true f.b();//f.b is not a function F.a();//true F.b();//true
总结:
*查找对象属性是查找对象的原型链,查找原型链是根据隐式原型链*隐式原型是由实例决定的 A.prototype={//显示原型 n:2,//给显示原型重新赋值,只会影响后面创建的对象 m:3, } console.log(b.n,b.m,c.n,c.m);//1 undefined 2 3 A.prototype.m=5;给原型对象添加属性,对前后创建对象都有影响 console.log(b.n,b.m,c.n,c.m);//1 5 1 5
相关推荐:
以上是JavaScript中的原型與原型鏈詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!