将函数定义在全局作用域中,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全,将函数定义了构造函数中也不太好,因为每调用一次函数,就会创造一个空间存放该函数,造成资源浪费
而原型的出现就解决了这一问题
我们所创建的每一个函数,解析器都会向函数添加一个叫做prototype的属性
而prototype这一属性对应的对象就叫做原型
如果函数作为普通函数调用,则prototype属性没有任何作用
如果函数作为构造函数调用,则构造函数创建的对象中都会有一个隐含属性,指向该构造函数的原型对象
隐含属性叫做__proto__
原型对象就相当于一个公共区域,所有同一类的实例都可以访问到这个原型对象
我们可以将所有实例的共有属性和方法 统一设置到原型对象中
当我们访问一个对象的属性时,先会在自身中寻找,如果有则直接使用,如果没有,就会去这一类对应的原型对象中寻找,如果找到则直接使用
以后我们创建对象时,可以将这些对象的共有属性和方法,统一添加到构造函数(类)的原型中
//构造函数
function Person(name,age){
this.name=name;
this.age=age;
}
//向Person类的原型中添加所有对象的公共方法 sayHello
Person.prototype.sayHello=function (){
console.log(this.name);
}
// console.log( Person.prototype);
//调用构造函数
var per1=new Person("孙悟空",18);
var per2=new Person("猪八戒",28);
var per3=new Person("沙和尚",38);
per1.sayHello();//先会在自身对象中找这个函数,没有就去原型对象找这个函数
per2.sayHello();
console.log( per3.proto);
in运算符
通过该运算符可以判断一个对象中是否含有指定的属性,返回值是true,或false
语法:“属性名” in 对象名
如果我们这个属性是添加在原型中的,那么对实例进行in运算结果会是怎样呢
//构造函数忽略
MyClass.prototype.name=“我是原型中的属性”
var mc=new MyClass();
console.log(“name” in mc)//返回值居然是true
这说明了使用in运算符检查对象是否包含某一属性,如果对象不包含此属性,但是原型中有,也会返回 true
可以使用每个对象自带的hasOwnProperty()方法来检查对象自身中是否包含某个属性
hasOwnProperty()方法以hasOwnProperty属性存在对象中
mc.hasOwnProperty("name") //就会返回false;
mc.age=17;
mc.hasOwnProperty("age") //就会返回true
该方法只有当对象自身中含有该属性时,才会返回true
原型对象也是对象,所以它也有原型
当我们使用一个对象的属性或方法时,会现在自身寻找,如果自身没找到,就去对象的原型中找
如果对象的原型中没有,就去对象的原型的原型(叫做Object)中找直到找到Object对象的原型
Object对象的原型没有原型,如果在Object原型中都没有找到,则返回undefined
自己–>爸爸–>爷爷-(也叫Object)->Object对象原型
对象–>对象的原型–>原型对象的原型–>原型对象的原型的原型
• 所谓不再使用的对象,指的是没有被任何 一个属性(变量)引用的对象。
• 垃圾回收的目的是,使开发者不必为对象 的生命周期管理花费太多精力