Clement

如果丢掉盔甲,我依然是骄傲帅气的骑士。

  • 菜单
  • 标签
  • 友情链接
  • 关于我
  • 擅长前端各项技能,喜欢折腾新技术,对JavaScript/Html/CSS相关客户端、服务端(Java/Node.js)以及数据库(MYSQL/SQLServer)知识很感兴趣。

    JavaScript创建对象之理解原型对象(笔记4)

    上次已经详细分析了Person构造函数、Person构造函数的原型对象以及Person的实例对象之间的关系,现在我们来探讨它们的作用域链之间的关系。
    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    unction Person(name,age,job)
    {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayNationality = function(){
    alert(this.nationality);
    };
    }
    Person.prototype.name = "Ken";
    Person.prototype.age = 18;
    Person.prototype.job = "Student";
    Person.prototype.nationality = "China";
    Person.prototype.sayName = function () {
    alert(this.name);
    }
    var person1 = new Person('Nicholas',29,'Software Engineer');
    person1.sayName();//Nicholas
    person1.sayNationality();//China
    var person2 = new Person('Nicholas',29,'Software Engineer');
    person2.sayName();//Nicholas

    每当代码
    person1.sayName();//Ken
    person1.sayNationality();//China
    person2.sayName();//Ken
    读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这个属性,则返回该属性的值。也就是说,在调用person1.sayName()的时候,会先后执行两次搜索。首先,解析器会问:“实例person1有sayName属性吗?”答:“没有。”然后,它继续搜索,再问:“person1的原型有sayName属性吗?”答:“有。”于是,它就读取那个保存在原型对象中的函数。同理,当调用person1.sayNationality方法的时候,会先在当前实例对象中搜索有没有sayNationality方法,有就调用这个方法,在执行sayNationality方法的时候,实例对象并没有this.nationality属性成员,它就会通过实例对象的prototype属性的作用域链搜索nationality标识符,在person1的原型对象上有nationality属性,于是就可以正常读取它保存的值。当我们调用person2.sayName()时,将会重现相同的搜索过程,得到相同的结果。而这正是多个对象实例共享原型所保存的属性和方法的基本原理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    person1.constructor //它指向Person构造函数
    //从Person构造函数指向原型对象,这样就可以访问原型对象的成员
    person1.constructor.prototype
    person1.constructor.prototype.name //Ken;
    /*underfined,在所有对象实例中都是无法访问到[[Prototype]]
    */
    person1.prototype;//underfined
    /*
    怎样可以不通过person1.constructor来访问prototype呢?可以利用原型对象上的isPrototypeOf()方法来确定person1与原型对象之间是否存在这种关系,若存在就通过Object.getPrototypeOf(person1).name来访问person1的原型对象的成员name属性。
    */
    if(Person.prototype.isPrototypeOf(person1))
    {
    alert(Object.getPrototypeOf(person1).name)//Ken
    }

    虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型的值。如果我们在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。来看下面的例子。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function Person(){}
    Person.prototype.name = "Ken";
    Person.prototype.age = 18;
    Person.prototype.job = "Student";
    Person.prototype.sayName = function () {
    alert(this.name);
    }
    var person1 = new Person();
    var person2 = new Person();
    person1.name = "Greg";
    alert(person1.name); //"Greg" 来自实例对象的成员
    alert(person2.name);//"Ken" 来自原型对象的成员

    不过使用delete操作符则完全可以完全删除实例属性,从而让我们能够重新访问原型中的属性,代码如下所示。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function Person(){}
    Person.prototype.name = "Ken";
    Person.prototype.age = 18;
    Person.prototype.job = "Student";
    Person.prototype.sayName = function () {
    alert(this.name);
    }
    var person1 = new Person();
    var person2 = new Person();
    person1.name = "Greg";
    alert(person1.name); //"Greg" 来自实例对象的成员
    alert(person2.name);//"Ken" 来自原型对象的成员
    delete person1.name;
    alert(person1.name);//"Ken" 来自原型对象的成员

    使用hasOwnProperty()方法可以检查一个属性是存在于实例中,还是存在于原型中。这个方法(不要忘了它是从Object继承来的)只在给定属性存在于对象实例时,才会返回true。

    1
    2
    //在上面代码的最后一行加上这行代码
    alert(person1.hasOwnProperty("name"));//false

    原型与in操作符
    有两种方式使用in操作符:单独使用和在for-in循环中使用。在单独使用时,in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

    1
    2
    //在上面代码的最后一行加上这行代码
    alert("name" in person1); //true

    文章目录
  • 拉格朗日中值定理学习笔记
  • 罗尔定理学习笔记
  • 零点定理学习笔记
  • JavaScript创建对象之理解原型对象(笔记4)
  • JavaScript创建对象之理解原型对象(笔记3)
  • JavaScript创建对象之构造函数模式(笔记2)
  • JavaScript创建对象之工厂模式(笔记1)
  • ECMAScript属性类型
  • 各大互联网公司前端笔试面试题–JavaScript篇(持续更新)
  • Web异步交互技术之iframe
  • html页头设置不缓存
  • GitHub配置与使用总结(持续更新)
  • 七牛的qrsbox命令行工具使用 for osx
  • VirtualBox在OSX下无法识别U盘,提示Failed to create a proxy device for the USB device. (Error: VERR_PDM_NO_USB_PORTS).
  • sublime基本介绍和使用技巧(持续更新)
  • 第一次和大家见面
  • 数据迁移中,敬请期待!
  • css+div解决文字溢出控制显示字数
  • js的defer属性对dom加载的影响
  • Web前端开发学习教程