首页 > 技术文章 > 函数原型

laiso 2017-11-28 19:58 原文

1. 可访问属性

var person={

        name:"王瑞睿",

        age:12

   };

   //访问器属性,访问器属性不包括数据值,但是包括getter与setter函数,setter is used to change the object`s property value

   Object.defineProperty(person,"name",{     

       get:function(){

           alert("sss");

       },

       set:function(newvalue){

           if(newvalue=="object"){

               this.age++;

           }

       }

   })

   Object.defineProperty(person,"sex",{

       writable:false,

       value:"man",

       

   }) //数据成员得属性都包括可读性,可遍历性,可删除性和value,通过defineProperty()函数是指明对象的数据属性或者是访问器属性

person.name="object"; name为访问器属性

console.log(person.age);   13

console.log(person.sex);   man

person.sex="woman";  

console.log(person.sex);  man(只读)

2.configurable

需要注意的是:对象的可删除性在被修改为false之后,对象的configurable就不能被修改,否则出错

 Object.defineProperty(person,"height",{

//     writable:true,

//     configurable:false,

//     value:175,

// })

// Object.defineProperty(person,"height",{

//     configurable:true,  //error

//     value:175,

// })

 

//defineProperties()

3.defineProperties()

var students={

    name:"jack",

}

Object.defineProperties(students,{

    age:{

        writable:true,

        value:15

    },

    height:{

        writable:true,

        value:175

    },

    _age:{

        get:function(){

           console.log(this.age);    

        },

        set:function(newvalue){

            if(newvalue>=15){

                this.height+=(newvalue-15)*5;

            }

        }

    }

    

})

console.log(students.name);

students._age=19;

console.log(students.height); 195

 

4.getOwnPropertyDestriptor()返回一个数据类型的对象

Object.getOwnpropertyDesctriptor()

var age=Object.getOwnPropertyDescriptor(students,"age"); //数据类型

console.log(age.writable+" "+age.value+" "+age.configurable);

注意:getOwnPropertyDescriptor()只是用于实例属性,而不是用于原型属性,如果要查看原型的数据类型,必须直接调用原型

var _age=Object.getOwnPropertyDescriptor(students,"_age");//访问器类型

console.log(typeof _age.get);  function

 

5.构造函数

//工厂模式

 function Students(fromwhere,ages,thename){

     this.name=thename;

     this.place=fromwhere;

     this.age=ages;

 }

 Students.prototype.show=function(){

         alert(this.name+this.age+"岁"+"住在"+this.place);

 }

  var stu1=new Students("shanxi",12,"王瑞睿");

每一个被实例化的对象都有一个constructor属性,指向构造函数。用来标识对象类型

console.log(stu1.constructor==Students);

object instanceof ObjectName 是一个检测对象类型的函数。

console.log(stu1 instanceof Object); true

console.log(stu1 instanceof Students);  true

 

构造函数本身是一个函数,在不用new来声明一个对象的时候 ,和普通函数是一样的,但是对象是window

Students("ss",13,"ss"); //对象指向window

console.log(window.place); //ss

 

//也可以通过call函数或者apply函数进行传参

//var o=new Object();

//Students.call(o,"ww",14,"ww");

//console.log(o.place);

6. 函数原型prototype

 

函数原型:prototype属性就是包含特定类型的所有实例共享的原型函数,本属性针对的是整类对象而不是针对某个对象,

每一个函数在创建时就会有一个prototype对象,成为原型对象,原型对象有一个属性constructor(指针)指向构造函数。

当调用构造函数实例化对象的时候,实例化对象被添加一个[[prototype]]属性,是一个指针,指向构造函数.prototype。

也就是说,实例化对象与构造函数的原型有关,而不和构造函数有关系!!!!

实例化对象调用属性或者方法是一个寻找的过程,从对象实例到原型依次寻找,当在对象实例中找到就返回,没找到才会去原型找,涉及一个"隐藏""遮盖"的概念

使用原型可以使所有实例的对象共享它(原型)所包含的属性和方法,类似于继承或者是static

 function Students(fromwhere,ages,thename){

     this.name=thename;

     this.place=fromwhere;

     this.age=ages;

 }

 Students.prototype.show=function(){

         alert(this.name+this.age+"岁"+"住在"+this.place);

 }

var stu1=new Students("shanxi",12,"王瑞睿");

var stu2=new Students("天津",13,"郑婉君");

console.log(stu1.show()==stu2.show());  true

 

console.log(Students.prototype.isPrototypeOf(stu2))   stu2是否与Students.prototype建立了某种联系

console.log(Object.getPrototypeOf(stu1)==Students.prototype);  Object.getPrototypeOf(object)  获得一个与object所具有某种联系的原型

console.log(Object.getPrototypeOf(stu1).show);

 

代码读取某个对象的某个属性的时候,都会执行一次搜索,先从对象实例开始,如果在实例中找到了值,则返回,就不用在向原型搜索,

当在实例中找不到时,才会向原型进行寻找,所以就会面临一个隐藏覆盖的问题,当原型的某个属性与实例中的属性重复时,原型的属性就被遮盖住了。

但是不管你怎么修改实例中的属性值,只是修改了实例中的值,而对于原型中重复的那个属性值而言毫无变化,但是你可以删除实例中的值,然后原型的值又”重见天日“

function Person(name,age,sex){

    this.name=name;

    this.sex=sex;

    this.age=age;

}

Person.prototype.age=17; //对象是在对象外定义的,而不是对象内

var person=new Person("ss",19,"man");

//delete person.age;// 根据对象属性configurable,对属性进行删除。

console.log(person.age);  //19  

7.hasOwnProperty()

//从Object继承来的hasOwnProperty() 是检测属性是在原型中还是在实例中,存在于实例时,返回true,存在于原型时,返回false

console.log(person.hasOwnProperty("age"));  //true

//原型与in操作符

//当in单独使用的时候 ,in可以判断某属性是否存在于某对象中,存在就返回true,而不管是不是原型或者实例中,

console.log("age" in person); //true

function hasporptotyperoperty(object,name){

    return !object.hasOwnProperty(name)&&(name in object);

}  //判断属性是否在原型中。

//原型和 For-in

//使用for-in循环,可以返回所有可枚举的实例化属性和原型属性,并且包括屏蔽了原型中方法的实例化属性。但是在爱IE8之前存在问题。

//取得对象上所有可枚举的实例属性,可以通过ES5的Object.keys(),返回一个属性数组。接受一个对象作为参数。

//console.log(Object.keys(Person.prototype));  //获得Person对象的原型中所有的可枚举属性

//console.log(Object.getOwnPropertyNames(Person.prototype));//获得Person.prototype中所有的属性

//直接把prototype看作一个对象直接赋值,

8.原型重写:1.prototype.constructor的指向问题被更改,2.与最初的prototype的联系切断。

 

function animals(){

}

1.var pig=new animals(); //此时pig构造函数的[[ptototype]]指针指向的是最初原型,并且重写原型对象打断了之前与最初原型的联系。这是undefined的原因

但是 1、2 如果调换位置的话,构造函数与函数原型的联系就重新连接。

2.animals.prototype={

    constructor:animals,

    legnum:2,

    headnum:4

}

console.log(pig.legnum); undefined

console.log(animals.prototype.constructor==animals); //true

但是需要注意的是,重写原型函数,原先的函数的prototype属性的constructor属性不再指向animal函数,而是指向Object,当然我们可以在原型对象中指定constructor的值。

9,原型的缺点

当原型中包含着包含引用类型值的时候,原型会因为个别对象的改变,而改变所有的对象属性

 

推荐阅读