JavaScript原型属性的详细说明
每个函数都有一个原型属性,它是对一个对象的引用,这个对象被称为原型对象。原型对象包含由函数实例共享的方法和属性。也就是说,当一个函数被用作构造函数调用时(用新的操作符调用),新创建的对象将继承原型对象的属性和方法。
私有变量和函数在指定原型之前,通过说一些相关的事情,可以更好地理解原型的设计意图。之前写的一篇JavaScript命名空间博客提到了JavaScript的功能范围。如果函数中定义的变量和函数不提供外部接口,外部将无法访问,即成为私有变量和私有函数。
函数Obj(){ var a=0;//私有变量var fn=function(){//private function } }这样一来,变量a和函数fn就不能在函数Object Obj之外访问,它们变成私有的,只能在Obj内部使用,即使是函数Obj的实例仍然不能访问这些变量和函数。
var o=new Obj();console . log(o . a);//未定义的console . log(o . fn);//未定义的静态变量和函数
定义函数时,属性和函数由“.”添加仍然可以通过对象本身进行访问,但是不能访问它的实例。这样的变量和函数分别称为静态变量和静态函数。使用过Java和C#的同学都能很好的理解静态的含义。
function Obj(){ } Obj . a=0;//静态变量Obj.fn=function(){ //静态函数} console . log(Obj . a);//0 console . log(type of Obj . fn);//函数var o=new Obj();console . log(o . a);//未定义的console.log(类型为o . fn);//未定义的实例变量和函数
在面向对象编程中,除了一些库函数之外,我们在定义对象的时候还是要同时定义一些属性和方法,实例化之后可以访问,JavaScript也可以
function Obj(){ this . a=[];//实例变量this . fn=function(){//instance method } } console . log(type of Obj . a);//undefined console . log(type of Obj . fn);//undefined var o=new Obj();console . log(o . a的类型);//对象console.log(类型为o . fn);//功能这可以达到上述目的,但是,
function Obj(){ this . a=[];//实例变量this.fn=function(){ //实例方法} } var O1=new Obj();O1 . a . push(1);O1 . fn={ };console . log(O1 . a);//[1] console.log(类型为O1 . fn);//对象var O2=new Obj();console . log(O2 . a);//[]console . log(O2 . fn的类型);//函数上面的代码完全按照预期运行,但它也显示了一个问题。a和fn在o1中被修饰,但在o2中没有改变。因为数组和函数都是Objects和reference类型,所以它显示了o1和o2中的属性和方法具有相同的名称,但它们不是引用,而是obj对象定义的属性和方法的副本。
属性没有问题,但是方法有一个很大的问题,因为方法都在执行完全相同的功能,但是它们被复制成两个副本。如果一个函数对象有几千个实例方法,那么它的每个实例都必须保留几千个方法的副本,这显然是不科学的,这是一个很大的问题。原型应运而生。
原型
每当创建新函数时,都会根据一组特定的规则为该函数创建一个原型属性。默认情况下,原型属性将默认获得一个构造函数属性。这个属性是指向原型属性所在的函数的指针,其中一些被绕过。写代码,上图!
函数Person(){ }
从上图可以看出,Person对象会自动得到prototype属性,prototype也是一个对象,会自动得到一个构造函数属性,指向Person对象。
当一个构造函数被调用来创建一个实例时,一个内部指针(在许多浏览器中被命名为__proto__)将被包含在该实例中,以指向该构造函数的原型。这种连接存在于实例和构造函数原型之间,但不存在于实例和构造函数之间。
函数Person(name){ this . name=name;} person . prototype . print name=function(){ alert(this . name);} var Person 1=new Person(' Byron ');var person2=新人(' Frank ');
Person的实例Person1中包含name属性,并自动生成一个__proto__属性,该属性指向Person的原型,可以访问prototype中定义的printName方法,大概是这样的
编写一个段落程序来测试原型中的属性和方法是否可以共享
函数Person(name){ this . name=name;} person . prototype . share=[];person . prototype . print name=function(){ alert(this . name);} var Person 1=new Person(' Byron ');var person2=新人(' Frank ');person 1 . share . push(1);person 2 . share . push(2);console . log(person 2 . share);//[1,2]果然!事实上,当代码读取一个对象的属性时,它将执行一次搜索。目标是具有给定名称的属性。搜索首先从对象实例开始,如果在实例中找到属性,则返回。如果找不到,就找原型。如果仍然没有找到,它将继续递归原型的原型对象,直到找到为止。如果它递归到对象,它将返回一个错误。同样,如果在实例中定义了与原型同名的属性或函数,原型的属性或函数将被覆盖。
函数Person(name){ this . name=name;} person . prototype . share=[];var Person=new Person(' Byron ');person . share=0;console . log(person . share);//0构造一个简单的对象,而不是原型中的[]
当然,原型并不是为了解决上述问题而专门定义的,但它解决了上述问题。了解这些知识可以构建一个复用率很高的科学对象。如果希望在原型中定义实例对象的属性或函数,如果希望在原型中定义每个实例拥有的属性或方法,可以通过构造函数传递实例化参数。
函数Person(name){ this . name=name;} person . prototype . share=[];person . prototype . print name=function(){ alert(this . name);}以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。
版权声明:JavaScript原型属性的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。