javascript基础-原型对象
1 原型对象
我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象。
如图,每个我们创建的函数对象都会指向一个自己的原型对象。
- 如果函数作为普通函数调用prototype时没有任何作用(函数名称()调用的方式)
- 当函数以构造函数的形式调用时,他所创建的对象中会有一个隐含的属性指向该构造函数的prototype(原型对象),我们可以通过__proto__来访问该属性。
指向的是同一个原型对象,也就是上面的0x123
我们可以看到,p对象和p2对象指向的是同一个原型对象的地址。
不管有几个对象,都是一样的。也就是说,原型对象是一个类创建的所有对象的公共区域,该类的所有对象都可以访问到这个原型对象。所以一般我们将某个类的所有对象公有的内容设置到原型对象里。
可以看出,确实是公共的区域。
通过类设置原型对象,虽然p2对象中并没有name属性,但是公共区域有,在自身区域中找不到后,会去公共区域找。
如果我们在p2对象中设置了name属性,那么输出时自身有,就直接用自身的name了。
如图:
在原型对象中添加函数类型属性:
和普通类型属性一样,也是可以的。
使用原型对象,修改44次文档代码:
前一章节我们为了优化内存,将对象中重复的函数类型属性hanshu提取到了全局中,但是会存在一个隐患,那就是一旦协同开发中,其他程序员也使用了hs这名称定义函数的时候,会覆盖我们创建的hs函数,所以我们通过原型对象就可以解决这个问题:
首先实例化Persion让prototype生成并指向,然后向原型对象(prototype)中设置公共属性,这样Persion类的任何一个实例化的对象,都可以访问到公共区域的函数了,而且还避免了将公共函数放到全局的名称污染的问题。
通过类名定义也可以:
该法不必在定义原型对象属性前进行实例化操作,因为我们是通过类名直接定义的。
-------------------------------------------------------------------------------------------------------------------------
1 关键字in:判断某对象中是否存在相同名称的属性(原型对象中的属性也算)
2 hasOwnProperty()方法,查询自己对象中是否有某个属性
我们发现p对象中并没有hasOwnProperty()方法,那么p的原型中有没有呢?
我们发现p的原型对象自身中也是没有hasOwnProperty()方法的,那么该方法到底在哪?
如图:
其实原型对象中也存在原型对象的,就像普通对象中存在原型对象是一样的。
我们可以看到,果然
当然也可以用in关键字查询,更简单:
因为关键字in会查询所有的嵌套的对象包括嵌套的原型对象。
注意:原型对象的原型对象,只有这两层,并不是无限嵌套的:
注意:如果在对象中查询是否存在某个属性是,如果第二层原型对象中都不存在的时候,会一直向上查询到Object对象,如果Object对象中还没有,那么返回undefined,注:Object对象是没有原型对象的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> function Person(){ } var p=new Person(); var p2=new Person(); /* console.log(Person.prototype);//原型对象 console.log(p.__proto__);//结果与上面一致 */ /* // 通过对象p向原型对象中添加属性 p.__proto__.name="p"; // 通过对象p2从原型对象中读取属性 console.log(p2.__proto__); // 结果 p和p2的protp原型对象中属性是公共的区域 */ /* Person.prototype.name="p"; console.log(p2.name);//如果p2自身没有name属性,则在公共区域找name属性的值 // 通过类设置原型对象,虽然p2对象中并没有name属性, // 但是公共区域有,在自身区域中找不到后,会去公共区域找。 p2.name="list"; console.log(p2.name); // 如果我们在p2对象中设置了name属性,那么输出时自身有,就直接用自身的name了。 */ // 在原型对象中添加函数类型属性: // 公共区域的函数 Person.prototype.fun=function(){ alert("p"); } console.log(p2.fun()); console.log(p.fun()); </script> </head> <body> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> function Person(name,gender,age){ this.name =name; this.gender =gender; this.age =age; // this.hanshu=hs; } function hs(){ alert(this.name); } var person1 = new Person("李红","女",20); // 通过原型对象定义公共的方法 person1.__proto__.hanshu=function(){ alert(this.name) } console.log(person1.hanshu()); </script> </head> <body> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> function Person(){ } var person1 = new Person(); // 向构造函数的原型对象中添加name属性 Person.prototype.name="lihong"; console.log(person1.name); // 通过关键字in检查name属性是否存在p对象中存在 console.log("name" in person1);//true // hasOwnProperty()方法,查询自己对象中是否有某个属性 console.log(person1.hasOwnProperty("name"));//false console.log(person1.__proto__.hasOwnProperty("hasOwnProperty"));//false // p的原型对象自身中也是没有hasOwnProperty()方法的 console.log(person1.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true // 在p的原型对象的原型对象中存在该方法。 // 注意:原型对象的原型对象,只有这两层,并不是无限嵌套的: // 可以用in关键字查询,更简单: console.log("hasOwnProperty" in person1);//true // 因为关键字in会查询所有的嵌套的对象包括嵌套的原型对象。 // 注意:如果在对象中查询是否存在某个属性是,如果第二层原型对象中都不存在的时候,会一直向上查询到Object对象,如果Object对象中还没有,那么返回undefined,注:Object对象是没有原型对象的。 </script> </head> <body> </body> </html>