和我一起学习Javascript的原型原型和原型链
每个函数都有一个原型的属性,这个属性是一个对象的引用,该对象被称为原型对象,原型对象包含的属性和方法的函数实例共享,作为构造函数调用(使用new运算符调用)时,新创建的对象将从原型对象继承和方法的性质,不同于传统的面向对象语言,Javascript的继承机制是基于原型,不类。
1。私有变量、函数
我们可以说几个相关的东东在原型原型更好理解设计意图。在你知道Javascript原型链,有必要了解Javascript第一范围链。Javascript的功能范围、变量和函数的定义在函数中,如果没有提供外部接口,将外部无法访问,即私有变量和私有函数。
函数的Obj(){
var = 0; /私有变量
Var(FN =函数)
}
}
所以它是不可能访问的变量和函数fn外部函数对象的Obj,他们成为私人的,只能用在obj,即使对象实例的功能仍然无法访问这些变量和函数。
var o =新的对象();
console.log(o.a); / /未定义
console.log(o.fn); / /未定义
2。静态变量和函数
在定义函数时。添加的属性和功能,由物体本身获得仍然可以访问,但却获得这样的情况下,变量和函数称为静态变量和静态函数,用java和c #学生很好地理解静态的意义。
功能(obj){ }
Obj。= 0; / /静态变量
(obj。FN =功能){ / /静态函数
}
console.log(obj,); / / 0
console.log(typeof obj,FN); / /功能
var o =新的对象();
console.log(o.a); / /未定义
console.log(typeof o.fn); / /未定义
3,案例变量,函数
在面向对象编程中,除了一些库函数,我们还希望在定义对象时同时定义一些属性和方法,在实例化之后可以访问这些属性和方法,Javascript也可以这样做。
函数的Obj(){
这个。
(这一点)
}
}
console.log(typeof对象。一个); / /未定义
console.log(typeof obj,FN); / /未定义
var o =新的对象();
console.log(typeof O.A); / /对象
console.log(typeof o.fn); / /功能
然而,这可以达到上述目的。
函数的Obj(){
这个。
(这一点)
}
}
VaR O1 =新的对象();
(1)o1.a.push;
O1 FN = { };
console.log(O1,); / / { 1 }
console.log(typeof O1,FN); / /对象
VaR O2 =新的对象();
console.log(O2,); / / { }
console.log(typeof O2,FN); / /功能
上面的代码运行结果与预期完全一致,但也显示了O1的问题,修改和FN,但O2没有变化,因为数组和函数是对象,是一个引用类型,表明该方法和在O2具有相同的名称,但它虽然不是一个参考O1属性和方法的性质,一个副本的obj对象的属性和方法,但定义。
这个属性没有什么问题,但是该方法的问题是巨大的,因为它是完全相同的功能,但两份,如果一个函数对象是1000和实例方法,则每个实例必须保持1000的方法复制,这显然是不科学的,可肿么办,原型是形成的。先看看对象的意义:
4,公共对象和函数对象
在Javascript中,一切都是对象!但对象也不同,它分为普通对象和函数对象,对象、函数是js的函数对象,下面举例说明
函数(F1){ };
Var(F2 =函数){ };
VAR F3 =新功能('str ',' console.log(STR));
新f1();
VaR O1 = { };
新对象();
console.log(类对象); / /功能
console.log(typeof功能); / /功能
console.log(typeof O1); / /对象
console.log(typeof O2); / /对象
console.log(typeof O3); / /对象
console.log(typeof F1); / /功能
console.log(typeof F2); / /功能
console.log(typeof F3); / /功能
在上面的例子中,O1 O2 O3是一个共同的目标,和F1 F2 F3是一个函数对象,如何区分,其实很简单,用新的函数创建的任何对象()是一个函数对象,而其他的都是普通objects.f1,F2,归根到底,是新函数的方式创建的函数对象(),也创造了新的功能()。
5,原型原型
在Javascript中,每当一个对象(函数)的定义,一些预定义的属性中包含的对象,一个函数对象的属性是对象的原型样机。注:对象不是原型,但原_ _属性。
原型对象实际上是一个共同的目标(除了function.prototype,这是一个函数对象,但它是非常特殊的。它没有原型属性。(以前,函数对象有原型属性):
函数(F1){ };
console.log(F1。原型) / / F1 { }
console.log(typeof F1。原型) / /对象
console.log(typeof函数原型) / /功能,这种特殊的
console.log(typeof对象。原型) / /对象
console.log(typeof函数原型。原型) / /未定义
从console.log(f1.prototype / / F1){ }输出结果可以看出,对象的一个实例是f1.prototype F1(这里是F1的对象的原型)。当F1被创建,它创建一个实例对象并将其分配到其原型。基本过程如下:
新的f1();
F1。原型=温度;
为什么Function.prototype是一个函数对象是解决。如上所述,新函数生成的所有对象()的函数对象,所以temp1是一个函数对象。
无功temp1 =新的功能();
function.prototype = temp1;
原型对象是什么main函数将用于继承,例如:
var =函数(名称){
this.name =名称
};
person.prototype.getname =函数(){
返回this.name; / /这个人= = > person.name这里原型对象
}
VaR XPG =新的人('xiaopingguo);
Xpg.getName(); / / xiaopingguo
从这个例子,我们可以看到,通过设置函数对象person.prototype属性,有人说一个共同的实例(例如:XPG),继承了这一特性。具体来说,如何进行传承,我们要谈论以下原型链。
故事中的深:无论什么时候,只要你创建一个新的功能,根据一组特定的函数来创建一个原型属性的规则(这也是一个对象),默认原型属性(对象)会得到一个构造函数(默认构造函数)属性,这个属性是一个指向函数的指针的原型属性,有些绕啊,写上面的代码!
功能人(){
}
根据上面的图,我们可以看到,人的对象自动获取原型的属性,和原型也是一个对象,它会自动获取一个构造函数的属性,它是指人的对象。
当我们调用构造函数创建一个实例的内部包含一个内部指针(很多浏览器这个指针的名字_原_)指向原型的构造函数,原型实例构造函数之间存在联系,但没有实例构造函数之间。
功能人(名称){
这个名字=名字;
}
人的原型。printname =函数(){
警报(这个名字);
}
VaR甲=新的人('byron);
var 2 =新的人('frank);
人把一个实例包含name属性,并自动生成一个_原_属性,该属性的人物原型,可以访问在一个原型中定义的printname方法,大概就是这样:
编写程序的一部分,测试原型中的属性和方法,以便共享。
功能人(名称){
这个名字=名字;
}
人。原型;
人的原型。printname =函数(){
警报(这个名字);
}
VaR甲=新的人('byron);
var 2 =新的人('frank);
(1)person1.share.push;
(2)person2.share.push;
console.log(2。分享); / / {1,2}
事实上 uff01in其实代码读取属性的对象将被再次执行时,搜索的对象是具有给定名称的属性。搜索从对象实例,如果属性实例中找到返回,如果没有找到原型,如果你还没有找到继续递归的原型对象,直到找到为止,如果递归对象仍然没有返回一个错误。同样的理由可以覆盖原型的性质如果属性或功能或功能等为原型的名字是在实例中定义的。--这是Javascript的原型链。
功能人(名称){
这个名字=名字;
}
人。原型;
无功的人=新的人('byron);
人,共享= 0;
console.log(个人分享); / / 0;不是原型{ }
6。原型链
JS在创建对象(无论是普通的对象或函数对象)的时候有一个叫原_ _内置属性,创建一个原型对象原型的函数对象。上面的情况
复制代码如下:console.log(XPG。__原__ = person.prototype / /真实)
同样,person.prototype对象也_原_属性,它指向创建它的函数对象(对象)的原型
复制代码如下:console.log(人。原型。__原object.prototype / /真实__ = = =)
此外,object.prototype对象也_原_属性,但它是专门为零
复制代码如下:console.log(对象的原型。__原__) / /空
字符串_原_直到对象。原型。_原_空链称为原型链:
原型链中的属性查找:
当物业找个对象,Javascript遍历原型链,直到找到一个给定名称的属性,找到最高达到原型链-这是object.prototype -但仍没有找到指定的属性,它将返回未定义,我们看一个例子:
函数(){
this.add =函数(x,y){
返回x y;
}
}
foo.prototype.add =函数(x,y){
返回x + y + 10;
}
object.prototype.subtract =函数(x,y){
返回x - y;
}
新富();
警报(f.add(1, 2)); / /结果是3,不是13
警报(f.subtract(1, 2)); / /结果是1
通过代码运行,我们发现减法器是我们说要找到得到的结果,但有点不同,加上方式,这就是我要强调的,当第一个属性在搜索中找到自己的属性时,如果没有找到那个原型,没有,继续下去。已经插入到对象原型中,所以在某种意义上,当使用for语句遍历属性时,效率也是一个问题。
我们需要注意的另一点是,我们可以将任何类型的对象分配给原型,但是不能分配原子类型的值,例如,下面的代码无效。
函数(富){ }
foo.prototype = 1; / /无效
7,构造函数、实例和原型对象之间的区别
实例是由构造函数创建的,实例是用构造函数属性(指向构造函数)和一个原始属性(指向原型对象)创建的,
在构造函数中,有一个原型属性,它是指向原型对象的指针。
在原型对象,也有一个指针(指向构造函数构造函数属性):person.prototype.constructor =人;
实例可以访问原型对象上定义的属性和方法。
在这里,甲和2的例子,和原型的原型对象。
再来一个栗子:
函数动物(名称)累积构造函数
{
this.name =名称; / /设置对象属性
}
Animal.prototype.behavior =(功能) / /对基类构造函数的原型添加行为的方法
{
警告(这是++这个名称);
}
var狗=新动物(狗);创建狗对象
var =新动物();创建猫对象
Dog.behavior(狗); / /对象直接调用行为的方法
Cat.behavior(); / /输出这是一只猫
警报(狗行为=猫行为。);
8。使用原型
原型使用1:
在使用原型之前,我们需要对代码做一个小的修改:
VAR计算器=功能(decimaldigits,税){
this.decimaldigits = decimaldigits;
This.tax = tax;
};
然后,通过将对象的文字数量分配给计算器对象的原型属性来设置计算器对象的原型。
calculator.prototype = { {
添加:函数(x,y){
返回x y;
},
减法:函数(x,y){
返回x - y;
}
};
警报((新计算器())。添加(1, 3)));
在我们可以使用新的计算器对象之后,我们可以调用Add方法来计算结果。
原型使用2:
第二种方法是在分配原型原型时立即分配函数的表达式,也就是说,下面的格式:
代码复制代码如下:calculator.prototype =函数(){ }();
它的好处在前面的项目中已经知道了,也就是说,它可以封装私有函数,通过返回的形式公开简单的使用名称,从而实现公共/私有的效果,并且修改后的代码如下所示:
(calculator.prototype =功能){
添加函数(x,y){
返回x y;
},
减法=函数(x,y){
返回x - y;
}
返回{
添加:添加,
减:减
}
(});
警报((新计算器())。添加(11, 3)));
同样,我们可以调用Add方法来计算新计算器对象之后的结果。
逐步陈述:
在使用原型时,存在一个限制,即原型对象是立即设置的。现在我们来讨论如何设置原型的每个属性。
无功basecalculator =函数(){()
为每个实例声明一个小数位数。
this.decimaldigits = 2;
};
/ /使用原型basecalculator延伸
basecalculator.prototype.add =函数(x,y){
返回x y;
};
basecalculator.prototype.subtract =函数(x,y){
返回x - y;
};
声明一个basecalculator对象的构造函数初始化十进制属性decimaldigits,2功能并建立原型的属性,即(x,y)加和减(x,y),当然,你也可以使用2种以上提到的任何一个,我们的主要目的是要看看如何设置basecalculator物体在真实计算机原型。
无功basecalculator =函数(){()
this.decimaldigits = 2;
};
basecalculator.prototype = { {
添加:函数(x,y){
返回x y;
},
减法:函数(x,y){
返回x - y;
}
};
重写原型:
当使用第三方js库时,有时他们定义的原型方法不能满足我们的需要,但也离不开库,所以这次我们需要在一个或多个属性或函数中重写它们的原型,我们可以继续声明相同的添加代码形式。覆盖前面的Add函数代码如下所示:
覆盖前面计算器的添加(函数)
calculator.prototype.add =函数(x,y){
返回x + y + this.tax;
};
新计算器();
警报(calc.add(1, 1));
这样,我们计算出的结果超过了原来的税收值,但是有一点需要注意:即重写的代码需要放在最后,这样我们就可以覆盖前面的代码。
9、hasownproperty功能
hasownproperty是object.prototype方法,这是一个好东西,他可以判断一个对象是否包含自定义属性和属性不是原型链,因为hasownproperty是Javascript处理只有一个但属性函数不搜索原型链。
修改/ object.prototype
object.prototype.bar = 1;
var:未定义};
foo.bar / / 1;
bar'in foo; / /真的
foo.hasownproperty('bar '); / /假
foo.hasownproperty(O); / /真的
只有hasownproperty能给出正确的和预期的结果,它可以遍历对象的属性是有用的。没有其他的方法可以用来排除属性对原型链,而不是定义在对象本身的属性。
But there is a nauseous thing: Javascript will not protect hasOwnProperty from being illegally occupied, so if an object happens to exist in this property, we need to use external hasOwnProperty function to get the correct result.
var { { { {
HasOwnProperty:函数(){
返回false;
},
酒吧:这是drans
};
foo.hasownproperty('bar '); / /总是返回false
使用hasownproperty对象 / / { },然后设置foo
{ }。hasownproperty.call(Foo,'bar '); / /真的
hasownproperty是唯一可用的方法时,它检查是否存在一个对象的一个属性。同时,当使用在循环遍历对象,它是推荐使用的hasownproperty方法,这将避免由原型对象扩展带来的干扰。让我们举个例子:
修改/ object.prototype
object.prototype.bar = 1;
var:2 };
对于(var I){
console.log(我); / /输出两个属性:酒吧和Moo
}
我们不能改变声明的行为,所以你只能用hasownproperty方法筛选结果。代码如下:
在这个例子中,变量是
对于(var I){
如果(foo.hasownproperty(I)){
console.log(我); / /哞
}
}
这个版本的代码是写它的唯一正确途径。由于我们使用hasownproperty,我们只输出哞这个时间。如果hasownproperty不使用,这些代码可能出错时的原生对象的原型,如Object.prototype,推广。
摘要:介绍了hasownproperty使用,不做任何代码运行环境的假设,不要认为本地对象已扩展。
10,扩大
_相对_属性
_相对_属性(IE浏览器不支持)是一个指针,指向原型对象的一个实例,它的作用是属性的构造函数构造函数的原型,通过这两个属性,属性和方法可以在原型访问。
在Javascript对象实例的本质是由一系列的属性,在这些属性中,有一个内在的、无形的特殊属性,_原_的属性,该对象实例原型的价值,该对象的实例只能有一个独特的原型。
代表构造函数的函数(box)
box.prototype.name =trigkit4 ; / /原型属性
box.prototype.age =21;
(box.prototype.run =功能) / /原型法
{
返回this.name + this.age + 'studying;
}
}
无功1 =新箱();
VaR Box2 =新箱();
警报(1。构造函数); / /结构特性,可以获得构造函数,
是原型指针位置,然后得到构造函数本身。
原型和原型_ _属性之间的差异
原型是原型对象的特殊属性。
_原_是普通对象的隐式属性,在新的时代,原型将对象的引用;
_相对_实际上是一个对象的属性,和原型属性的构造函数。_相对_只能用于学习或调试环境。
原型模式的执行流程
1。首先在构造函数实例中查找属性或方法,如果存在,立即返回。
2。如果构造函数的实例不是,则转到它的原型对象,如果存在,立即返回。
原型对象
代表构造函数的函数(box)
box.prototype.name =trigkit4 ; / /原型属性
box.prototype.age =21;
(box.prototype.run =功能) / /原型法
{
返回this.name + this.age + 'studying;
}
}
无功1 =新箱();
警报(1名); / / trigkit4,原型中的值
box1.name =李;
警报(1名); / /李,入境的原则
VaR Box2 =新箱();
警报(Box2。名称); / / trigkit4,原型的价值,由1不改
构造函数
函数框(){
this.name =法案;
}
box.prototype.name =trigkit4 ; / /原型属性
box.prototype.age =21;
(box.prototype.run =功能) / /原型法
{
返回this.name + this.age + 'studying;
}
无功1 =新箱();
警报(1名); / /账单,在原型的价值
box1.name =李;
警报(1名); / /李,入境的原则
总之,整理一下:
函数(人){ };
person.prototype.name =trigkit4 ;
person.prototype.say =函数(){
警报(嗨);
}
var =新的人();原型是P1和P2的原型对象。
VaR P2 =新的人(); / / P2是一个实例化的对象与__proto__属性里面,指向人的原型
console.log(P1。原型); / /定义,这个属性是一个对象,访问不
console.log(人。原型); / /人
console.log(人。原型。构造函数); / /内部原型对象也有一个指针指向构造函数(构造函数属性)
console.log(P1。__proto__); / /这个属性是一个指向对象的原型样机
(P1表示);实例可以访问原型对象中定义的属性和方法。
原型=原型对象
原型对象=构造函数=构造函数(模板)
的原型object.isprototypeof(实例对象)确定原型对象是当前对象。
以上是本文的全部内容,希望能对大家有所帮助。