web前端开发中关于面向对象(三)

来源:互联网 发布:linux修改tomcat内存 编辑:程序博客网 时间:2024/06/07 01:07
    在面向对象前篇中提到过原型的概念,说到原型,便又延伸出了关于原型的一个知识点——原型链。也许作为一名专业的前端开发人员来说,明白原型链的含义以及用法,但对于前端的爱好者和在校大学生而言,对于原型链的概念可能是第一次听说,所以,今天就和大家学习一下原型链。    一、含义    实例对象和原型对象组成的一条链式结构,链式结构之间通过__proto__链接起来,这条链就成为原型链。    例:
function Person(name){    this.name=name;}Person.prototype.showName=function(){    console.log(this.name);}var p=new Person("Sue");//以上函数的原型链p-->Person.prototype-->Object.prototype-->null//其中,-->表示__proto__,该原型链的含义为:p.__proto__指向其构造函数的原型Person.prototype,而构造函数的原型默认是Object的实例,因而指向Object.prototype,之后便结束为空,至于原理,请参照上篇web前端开发中关于面向对象(二)进行理解。
    通过几次的实验和验证可以发现,原型链的末端都是Object.prototype,所有的对象都直接或间接的继承Object。    二、精确判断数据类型的方法    判断数据类型不仅仅有typeof一种方式,且typeof方法只能判断一般的数据类型,得到的结果较为模糊,不够精准。若想要精确的判断数据类型,需用到Object.prototype上的toString方法。使用Object.prototype.toString方法判断数据类型需要改变this的指向,因而需要配合call一起使用。typeof与Object.prototype.toString的区别:
    var arr= [];    var fn = function(){};    var str = "str";    var obj = {};    var date = new Date();    var regExp = new RegExp();    console.log("toString判断结果:"+Object.prototype.toString.call(arr));    console.log("typeof判断结果:"+typeof arr);    console.log('------------------')    console.log("toString判断结果:"+Object.prototype.toString.call(fn));    console.log("typeof判断结果:"+typeof fn);    console.log('------------------')    console.log("toString判断结果:"+Object.prototype.toString.call(str));    console.log("typeof判断结果:"+typeof str);    console.log('------------------')    console.log("toString判断结果:"+Object.prototype.toString.call(obj));    console.log("typeof判断结果:"+typeof obj);    console.log('------------------')    console.log("toString判断结果:"+Object.prototype.toString.call(date));    console.log("typeof判断结果:"+typeof date);    console.log('------------------')    console.log("toString判断结果:"+Object.prototype.toString.call(regExp));    console.log("typeof判断结果:"+typeof regExp);/*结果:    toString判断结果:[object Array]    typeof判断结果:object ------------------    toString判断结果:[object Function]    typeof判断结果:function ------------------    toString判断结果:[object String]    typeof判断结果:string ------------------    toString判断结果:[object Object]    typeof判断结果:object ------------------    toString判断结果:[object Date]    typeof判断结果:object ------------------    toString判断结果:[object RegExp]    typeof判断结果:object*/
    三、函数和Function的关系    函数,在上篇已经提到过,在不同的情况下所担任的角色就各不相同,可作为构造函数、普通函数等。而普通函数在使用字面量声明时就是构造函数,`var fn=new Function(){}`有时候也可是构造函数。那么,函数和Function两者之间又有何关联?仅仅使用文字是解释不太明白的,还是让代码来告诉大家。
function foo(){...}console.log(foo.__prototype==Function.prototype);//trueconsole.log(Object.__proto__==Function.prototype);//trueconsole.log(Function.__proto__==Function.prototype);//true/*原型链:foo-->Function.prototype-->Object.prototype-->nullobject-->Function.prototype-->Object.prototype-->nullFunction-->Function.prototype*/
    四、关于defineProperty    Object中具有一个方法:defineProperty,该方法是定义特性。该方法具有三个参数。    (1)第一个参数:目标对象    (2)第二个参数:需要定义属性和方法的名字    (3)第三个参数:目标属性所拥有的特性,必须是对象    例:
var a={};Object.defineProperty(a,"b",{    value:1,    writable:true,    configurable:true,    enumerable:true});
    以上例子的意思是:为对象a定义了一个属性,该属性为b,且为b赋值为1。defineProperty中第三个参数,对象中各个属性的含义:    (1)value:属性的值   (2)writable:属性值是否可以被重写,默认为false,若为true,则可以被重写   (3)configurable:总开关,默认为false。总开关一旦为false,value、writeable、configurable就不可被重设   (4)enumerable:是否可以在for/in中循环遍历,默认为false   defineProperty方法的第三个参数对象中还有两个属性,get和set,若使用get和set者两个属性,则就不需要再同时使用以上四个属性。   (1)get:获取值   (2)set:赋值   例:
Object.defineProperty(a,"b",{    set:function(val){},    get:function(){}});
    我们可以通过defineProperty中的set和get者两个属性来实现数据的双向绑定。    例:
<input type="text" v-model="val"/><p v-model="val"></p><script>    var inp=document.getElementsByTagName("input")[0];    var p=document.getElementsByTagName("p")[0];    var obj={};    Object.defineProperty(obj,"val",{        get:function()            return inp.value;        },        set:function(val){            p.innerHtml=val;            inp.value=val;        }    });    inp.oninput=function(){        obj.val=inp.value;    }</script>
    五、实例判断    如何判断对象是否是构造函数的实例?instanceof:判断对象是否是构造函数的实例。如果构造函数的原型在原型链上,那么原型链开始的那个实例是所有原型所属的构造函数的实例。    例:
function Person(name){    this.name=name;}Person.prototype.showName=function(){    console.log(this.name);}function Student(num){    this.num=num;}Student.prototy=new Person("Sue");var stu=new Student(90);console.log(stu instanceof Student);//trueconsole.log(stu instanceof Person);//trueconsole.log(stu instanceof Object);//trueconsole.log(stu instanceof Function);//false//原型链://stu-->Student.prototype-->Person.prototype-->Object.prototype-->null
    六、属性判断    (1)hasOwnProperty():判断对象中是否有某个属性,该方法只能判断实例对象上的属性,不能判断原型对象上的属性。    (2)in:既可以判断实例对象上的属性,又可以判断原型对象上的属性    例:
var obj=new Object();obj.info="Sue";obj.name="Mike";Object.prototype.age="20";console.log(obj.hasOwnProperty("info"));//trueconsole.log("info" in obj);//trueconsole.log(obj.hasOwnProperty("name"));//trueconsole.log("name in obj);//trueconsole.log(obj.hasOwnProperty("age"));//falseconsole.log("age" in obj);//true
判断某个属性是否在原型上的方法:
if("info" in obj &&!obj.hasOwnProperty("info")){...}
    七、原型继承    在其他语言中,面向对象中也存在继承和封装。在前端开发中面向对象也存在着继承,前端将继承分为几种,今天先看一看原型继承。其实,在以上提到的知识中已经涉及到也使用到了原型继承。    例:
function Animal(name){    this.name=name;}Animal.prototype.showName={    console.log(this.name);}function Tiger(age){    this.age=age;}var tiger=new Tiger("12"); 
    以上代码块执行的结果只会输出12。老虎是动物的一种,按照常理而言,老虎应该具有动物的特性,那么执行以上代码块,老虎应该具有姓名和年龄两个属性才是合理的,而如今只输出了年龄,那么怎样才可以在不再Tiger构造函数中添加属性而获得Animal构造函数中的name属性?这里便涉及到--继承的知识点。若想要继承Animal,则代码块为:
function Animal(name){    this.name=name;}Animal.prototype.showName={    console.log(this.name);}function Tiger(age){    this.age=age;}Tiger.prototype=new Animal("caser");var tiger=new Tiger("12"); 
    如此,老虎便可继承Animal中的属性和方法,且它自身的方法和属性也不会被共享。这便是原型继承。但原型继承存在几个问题:    (1)无法在不影响所有实例的情况下,给要继承的构造函数传参    (2)继承的构造函数中的引用类型对于所有的实例是共享的    那么,又该如何解决原型继承存在的这些问题呢?请阅读下一篇。
阅读全文
0 0
原创粉丝点击