LOADING

JavaScript的原型

–>

/*
alert(typeof null);//null是一个对象的实例,但它并不指向Object构造器的实例,所以null instanceof Object是false。
//Object构造器的实例指向空的对象实例,var obj = new Object(),所以obj instanceof Object是true。空的对象实例是原型继承的根基。空的对象实例的proto属性(不可访问的,隐藏的)指向null
//所以null和空的对象实例,你是改变不了滴。
var num = 0;
for(var propertyName in null){
    num++;
    alert(propertyName);//null可以有属性,但没有一个属性
}

alert(num);//null的属性个数为0
*/

//从JavaScript的语言和对象系统的实现来讲,对象实例并没有原型,而构造器(Constructor)有原型,对象实例指向某个原型,对象实例不拥有原型
//
原型的含义:原型就是一个对象实例,如果构造器有一个原型对象实例A,则该构造器创建的实例(Instance)都必然指向A。
//
因此,你要理解,对象,对象实例,原型,构造器的概念。
//
Object是对象,也是构造器。new Object()返回一个对象实例,Object.prototype也是一个对象实例
var obj = Object.prototype;
var num = 0;
for(var n in obj){
   // num ++;
}
//alert(num);//显示为0,说明Object.prototype,没有一个属性。而Object.prototype对象实例来自于Object.constructor()对象,说明这个对象是空对象。

obj1 = new Object();//这个只是obj1对象实例,指向到Object.prototype对象实例
obj2 = {};//这个也是

obj2.value=10;//对obj2对象实例的属性,进行修改。自然不会更改Object.prototype对象实例,只是仅仅对obj2对象实例,增加了属性列表value 10 number。
//
为什么会这样,还不是为了节约内存使用

alert(obj2.value);
alert(obj1.value);//undefined,因为Object.value没有定义

Object.prototype.value = \’abc\’;//修改了Object.prototype对象实例,
alert(obj2.value);//但是这个还是显示10,说明对象实例首先访问自己的属性列表
alert(obj1.value);//如果没有,再访问自己指向的原型

上面虽然有点乱,总结起来就是null是什么,空的对象实例是什么,以及什么是对象,对象实例,原型,修改了原型会发生什么。

null是一个对象的实例,它没有一个内部的,不可访问的属性proto,有属于自己的属性列表,里面内容为空。

空的对象实例,它有一个内部的,不可访问的属性proto指向null;它也有一个属于自己的属性列表,里面内容为空。JavaScript语言自带的Object对象的prototype属性指向空的对象实例。

因为Object对象的prototype属性指向了空的对象实例,所以任何Object对象产生的实例,内部的不可访问的属性proto,指向空的对象实例。

Object.prototype是一个对象实例,它有自己的属性列表,可以对其属性列表增删查改。当然null和空的对象实例,你改不了。

下面讲一下Object.prototype.constructor属性,

function MyObject(){
}
//说明原型的构造器是一个对象,指向对象自身
alert(MyObject.prototype.constructor == MyObject);
//删除了MyObject原型的自身的属性列表,要知道delete不能删除var声明的东西,还不能删除原型继承的东西
delete MyObject.prototype.constructor;
//MyObject原型的构造器还存在,但指向了Object。这说明MyObject.prototype来自于Object的实例
alert(MyObject.prototype.constructor == Object);
alert(MyObject.prototype.constructor == (new Object()).constructor)

那为什么MyObject.prototype.constructor == MyObject一开始是这样?因为JS语言系统,对这个做了处理,逻辑如下:

var __proto__ = null;
function get_prototype
if (!_proto_) {
__proto__  =  new Object(); 
__proto__.construct = this;
}
return _proto_;

也就是说,MyObject.prototype先指向Object的实例,然后MyObject.prototype.constructor 指向自身对象(这里已经是对象实例的自身属性列表了)。

 

所谓对象的继承关系,通过对象的prototype属性来实现:

obj1 = new Object();//这个只是obj1对象实例,指向到Object.prototype对象实例
obj2 = {};//这个也是

obj2.value=10;//对obj2对象实例的属性,进行修改。自然不会更改Object.prototype对象实例,只是仅仅对obj2对象实例,增加了属性列表value 10 number。
//
为什么会这样,还不是为了节约内存使用

alert(obj2.value);
alert(obj1.value);//undefined,因为Object.value没有定义

Object.prototype.value = \’abc\’;//修改了Object.prototype对象实例,
alert(obj2.value);//但是这个还是显示10,说明对象实例首先访问自己的属性列表
alert(obj1.value);//如果没有,再访问自己指向的原型

// 1. 构造器
function Animal() {}; // 动物
function Mammal() {}; // 哺乳类
function Canine() {}; // 犬科
function Dog() {}; // 狗
function Cat() {}; // 猫
//
 2. 原型链表
Mammal.prototype = new Animal();
Canine.prototype = new Mammal();
Dog.prototype = new Canine();
Cat .prototype = new Mammal();
// 3. 示例函数
function isAnimal(obj) {
return obj instanceof Animal;
}
// 4. 示例代码
var dog = new Dog();
var cat = new Cat();
document.writeln(isAnimal(dog));

那么现在来讲讲,JS的原型继承方式:

面向对象三特性,封装,继承,多态。

所谓封装,就是访问权限了,private(只有内部能访问),protect(只有内部和子类能访问),public(谁都能访问)。

所谓继承,就是子类拥有父类的属性方法,当子类与父类方法同名时,子类能否调用父类方法。

所谓多态,就是子类不仅有父类的属性方法,也有自己独有的。能确认对象是否来自于这个类型,对象是否来自于这个类型的子类。as和is。

对于封装,JS只能做到private和public。

function father(){
    var privateString = \’I am private father\’;//私有变量
    this.publicString = \’ I am public father\’;//公有变量
    
    function privateFunc(){
        alert(privateString+publicString);
    }
    this.publicFunc = function(){
        alert(privateString+this.publicString);
    }
}
var faterInstance = new father();
faterInstance.publicFunc();
//faterInstance.privateFunc();出错
alert(faterInstance.privateString);//undefined
alert(faterInstance.publicString);

 

对于继承,JS只能做到子类拥有父类的属性方法。当子类与父类方法同名时,子类不能调用父类方法。

function father(){
    var privateString = \’I am private father\’;//私有变量
    this.publicString = \’ I am public father\’;//公有变量
    this.commonStrng = \’come on baby\’;
    
    function privateFunc(){
        alert(privateString+publicString);
    }
    this.publicFunc = function(){
        alert(privateString+this.publicString);
    }
    
}
function son(){
    //this.constructor = arguments.callee;
    this.commonStrng = \’I am son\’;
}

son.prototype = new father();//原型继承
var sonInstance = new son();
//sonInstance.publicFunc();
//
alert(sonInstance.commonStrng);//I am son
alert(sonInstance.constructor);//如果注释掉son函数里面的this.constructor = arguments.callee;这条语句,这里显示father函数的。因为上面son.prototype是fater的实例,也就是说//son.prototype.constructor是fater.prottotype.constructor,而fater.prottotype.constructor就是fater自身了。
//
alert(sonInstance instanceof son);//用来确认is操作
alert(sonInstance.constructor.prototype.constructor);//查找父对象,这里不管注释不注释son函数里面的this.constructor = arguments.callee;这条语句,都是显示father。原因是father.prototype没被修改过,所以father.prototype.constructor指向自身。

对于多态,JS只能做到确认对象是否来自于这个类型。

—————————————

对于JavaScript这门语言,基于原型的面向对象特性,不充足;基于闭包的面向函数式特性,不充足;基于eval和call的面向动态特性,不充足。但是把三种不充足结合在一起,就形成了JavaScript独特的充足。

原文链接:https://www.cnblogs.com/samwu/archive/2012/04/01/2429213.html
本文来源 互联网收集,文章内容系作者个人观点,不代表 本站 对观点赞同或支持。如需转载,请注明文章来源,如您发现有涉嫌抄袭侵权的内容,请联系本站核实处理。

© 版权声明

相关文章