对象可以分为函数对象和普通对象,prototype是函数对象才有的属性,__proto__是每个对象都有的一个属性,
通过new Function 的是函数对象,
重点:
原型(prototype)检测
1 var o3 ={}; //o3 = new Object() 2 console.log(o3.prototype); //undefined 3 console.log(o3 instanceof Object); //实例o3在不在Object构造函数中 true 4 5 function Demo() {} //函数对象 6 var d = new Demo(); //普通对象 7 console.log(d.prototype); //undefined 8 console.log(d instanceof Demo); 9 console.log(typeof Demo); 10 console.log(Demo.prototype); //{constructor: ƒ} 函数对象确实存在原型
原型对象
1 function Cat(name,color){ //构造函数 2 this.name = name; 3 this.color = color; 4 // this.type = '动物'; 5 // this.eat = function() { 6 // console.log('吃老鼠') 7 // } 8 }; 9 Cat.prototype.type = '动物'; 10 Cat.prototype.eat = function() { 11 console.log('吃老鼠') 12 } 13 var cat1 = new Cat('大明','黑色'); 14 var cat2 = new Cat('小明','白色');
函数对象对原型属性的检测
1 //in 无论是自身的还是原型属性都返回true 2 console.log('name' in cat1) ;//true 3 console.log('type' in cat1) ;//true 4 //hasOwnProperty() 自身的属性返回true 原型属性返回false 5 console.log(cat1.hasOwnProperty('name')); //true 6 console.log(cat1.hasOwnProperty('type')); //false
继承
apply() 与 call()
1 function Animal(){ //一个对象 父对象 2 this.type = '动物' 3 }; 4 function Cat(name,color){ //另一个对象 子对象 5 Animal.apply(this); //Animal在当前Cat对象中执行,将父对象的构造函数绑定到子对象上 6 this.name = name; 7 this.color = color; 8 }; 9 var cat1 = new Cat('大毛','黄色'); 10 cat1.type; //'动物'
直接继承
function Animal(){ //一个对象 父对象 this.type = '动物' }; function Cat(name,color){ //另一个对象 子对象 this.name = name; this.color = color; }; Cat.prototype = new Animal(); var cat1 = new Cat('大毛','黄色'); cat1.type; //'动物'
2)让Cat的原型直接继承Animal的原型
有个缺点就是Cat.prototype和Animal.prototyper指向同一个对象,指向同一块内存地址,当修改Cat.prototype的值时,Animal.prototype也会变化
function Animal(){}; //一个对象 父对象 Animal.prototype.type = '动物'; function Cat(name,color){ //另一个对象 子对象 this.name = name; this.color = color; }; Cat.prototype = Animal.prototype; Cat.prototype.abc = 'abc'; var cat1 = new Cat('大毛','黄色'); cat1.type; //'动物' console.log(Animal.prototype);//{type: "动物", abc: "abc", constructor: ƒ}
原型属性的CURD操作
原型继承说白了就是通过__proto__链接起来的
Cat.prototype 继承 的是 Animal实例对象 上面说到不管是函数对象还是普通对象它都有__proto__这个属性,原本cat1实例对象的__proto__指向的是 Cat函数对象的prototype对象,
但是现在Cat.prototype = new Animal(); 所以此时的cat1实例对象的__proto__指向的是 new Animal()实例 ===> 等价于 cat1.__proto__ = new Animal(); 通过cat1.__proto__可以获取Animal信息
function Animal(){ this.type= '动物'; }; function Cat(name,color){ //构造函数 this.name = name; this.color = color; }; Cat.prototype = new Animal(); var cat1 = new Cat('大明','黑色'); var cat2 = new Cat('小明','白色'); console.log(cat1.type); //动物 //获取属性 console.log(cat1.__proto__.type='猫科动物'); //猫科动物 //设置属性 cat1.__proto__.action="敏捷"; //删除属性 delete cat1.__proto__.type; //查看属性 console.log(cat1.__proto__.action);//敏捷 //查看继承的整个实例对象内容 console.log(cat1.__proto__); //Animal {type: "猫科动物"}
另一种写法
function Animal(){ this.type= '动物'; }; Animal.prototype.type2='动物2'; function Cat(name,color){ //构造函数 this.name = name; this.color = color; }; Cat.prototype = new Animal(); var cat1 = new Cat('大明','黑色'); var cat2 = new Cat('小明','白色'); // cat1.type; console.log(cat1.__proto__.__proto__.type2='abc'); //修改 打印出abc delete cat1.__proto__.__proto__.type2; //删除 console.log(cat1.type2); //已经删除,打印出undefined
原型链
f 实例 指向 F3的原型,此时F3原型存放着F2实例的属性, F3的原型又指向F2原型,F2原型对象里面存放着F1实例的值, 然后F2原型指向 F1原型.最终都会指向Object原型
function F1(){ this.name1 = 'f1'; }; function F2(){ this.name2 = 'f2'; }; function F3(){ this.name3 = 'f3'; }; F2.prototype = new F1(); F3.prototype = new F2(); var f = new F3(); console.log(f.name3); //f3