JavaScript之面向对象学习三原型语法升级

1、到目前为止,我们是时候分析下前面的使用原型语法来定义对象有哪些不足的地方,代码如下:

    function Person(){
    }
    Person.prototype.name="张三";
    Person.prototype.age=22;
    Person.prototype.job="coder";
    Person.prototype.sayName=function(){
        alert(this.name);
    }

当我们为Person对象每添加一个属性和方法,就要敲一遍Person.prototype,而且Person.prototype没有体现出封装性;

所以下面来改进原型语法,代码如下:

    function Person(){
    }
    Person.prototype={
        name:"张三",
        age:22,
        job:"coder",
        sayName:function(){
            alert(this.name);
        }
    }

改进之后的原型语法将Person.prototype设置为等于一个以对象字面量形式创建的新对象。最终的结果相同,但有一个列外:constrcutor属性不再指向Person了。

因为当我们每创建一个函数,同时就会创建一个prototype属性对象(原型属性对象),而这个对象会自动获得constructor属性。

而我们在这里使用的语法,本质上完全重写了默认的prototype属性对象,因此constructor属性也就变成了新对象的constuctor属性(该属性指向Object构造函数),不在指向Person函数,所以尽管instanceof操作符还能返回正确的结果,但通过constructor属性来确定对象的类型已经不可能了,如下代码可以说明:

    function Person(){
    }
    Person.prototype={
        name:"张三",
        age:22,
        job:"coder",
        sayName:function(){
            alert(this.name);
        }
    }
    var person=new Person();
    alert(person instanceof Object); //输出:true  因为person是Object的实例(Object是所有类的基类)
    alert(person instanceof Person); //输出:true  因为person是Person的实例
    alert(person.constructor==Object);
    alert(person.constructor==Person); //输出false  说明Person构造函数的Person.prototype属性对象(原型对象)内的constructor属性已经不指向Person函数,而
                                       //是指向Object函数

如果constructor属性真的很重要,我们可以向下面代码那样将它设回适当的值,代码如下:

    function Person(){
    }
    Person.prototype={
        constructor:Person, //自定义添加constructor属性,并让他指向Person函数
        name:"张三",
        age:22,
        job:"coder",
        sayName:function(){
            alert(this.name);
        }
    }
    var person=new Person();
    alert(person instanceof Object); //输出:true  因为person是Object的实例(Object是所有类的基类)
    alert(person instanceof Person); //输出:true  因为person是Person的实例
    alert(person.constructor==Object); //输出:false;  原因如下
    alert(person.constructor==Person); //输出:true  constructor:Person,=》在对象里面自定义了constructor属性,并让它指向了Person函数
    // 所以person.constructor重新指向了Person,而不是Object

注意:以上这种方式添加constructor属性会导致它的[[Enumerable]]设为true,而原生的constructor属性是不可枚举的,所以我们需要用ECMAScript 5中定义的Object.definePropery()方法来重新定义constructor属性,使他变成不可枚举的属性,且值是指向对象构造函数的指针,代码如下:

   function Person(){
    }
    Person.prototype={
        name:"张三",
        age:22,
        job:"coder",
        sayName:function(){
            alert(this.name);
        }
    }
    Object.defineProperty(Person.prototype,"constructor",{
        enumerable:false,
        value:Person
    });

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Vamei实验室

Python补充01 序列的方法

在快速教程中,我们了解了最基本的序列(sequence)。回忆一下,序列包含有定值表(tuple)和表(list)。此外,字符串(string)是一种特殊的定值...

1928
来自专栏武培轩的专栏

剑指Offer-数组中重复的数字

package Array; /** * 数组中重复的数字 *在一个长度为n的数组里的所有数字都在0到n-1的范围内。 * 数组中某些数字是重复的,但不...

3134
来自专栏欧阳大哥的轮子

排列组合

对有n个元素的集合S中的其中r个元素进行排列(n >= r)可以用如下几种方法来理解:

791
来自专栏GIS讲堂

js中的面向对象程序设计

面向对象的语言有一个标志,那就是他们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。

782
来自专栏前端知识分享

第186天:js深入理解构造函数和原型对象

1.在典型的oop的语言中,如java,都存在类的概念,类就是对象的模板,对象就是类的实例。但在js中不存在类的概念,js不是基于类,而是通过构造函数(cons...

1162
来自专栏Vamei实验室

Java进阶04 RTTI

运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息。 ...

2037
来自专栏GreenLeaves

JavaScript之面向对象学习一

1、通过Object构造函数和对象字面量来创建对象缺点:使用同一个接口创建很多的对象,会产生大量的重复代码。比如我需要创建人的对象,并且需要三类人,医生、工程师...

1916
来自专栏柠檬先生

es6 class

1.Es6引入了Class 类这个概念,作为对象的模板,通过class 关键字,可以定义类。 2.类和模块的内部,默认就是严格模式,所以不需要使用use str...

17110
来自专栏锦小年的博客

python学习笔记2.6-集合(set)

一般来说,python中常用的数据结构是:列表(list)、字典(Dict)、元组(tuple)。但是我们常常还会看到另外一种结构:集合(set)。 个人认...

2217
来自专栏进击的君君的前端之路

数据类型、运算符、流程控制语句

1714

扫码关注云+社区

领取腾讯云代金券