美文网首页前端开发那些事程序员前端开发
JavaScript难点——原型对象及其方法

JavaScript难点——原型对象及其方法

作者: 紫荆峰 | 来源:发表于2017-01-07 10:30 被阅读0次

0.前言

最近在网上学习原型这一块,看了很多博客,都不尽人意,因此笔者自己写一篇文章,尽量让大家明白这是怎么一回事。上一节我们只是了解一下js中的常用方法,同时也了解到prototype和constructor这两个属性,就是为了这一节做铺垫。

1.原型属性(prototype属性)

原型属性也叫prototype属性,每一个函数都有prototype属性,初始指向一个空对象(也叫原型对象)。我们可以给prototype进行修改,让它引用一个非空对象,只有在该函数是构造函数时才有实际意义。对于非构造函数,不会对函数的运行造成影响。当函数为构造函数时,我们可以通过原型属性修改原型对象,达到给用构造函数创建的对象增加属性和行为的功能。

2.利用原型添加方法与属性并修正constructor属性

首先定义一个构造函数

function Person(name, age){
            this.name = name;
            this.age  = age;
            this.say = function(){
                console.log("My name is " + this.name);
            };
        }
(1)利用原型添加方法和属性
Person.prototype.height = 175;
        Person.prototype.weight = 65;
        Person.prototype.run = function(){
            console.log("run");
        };
(2)用已存在的对象去给prototype赋值
Person.prototype = {
            height: 175,
            weight:65,
            run: function(){
                console.log("run");
            }
        };

定义上面两个方法时,我们发先一个问题,因为在上一节中我们了解到constructor是指向创建对象的构造函数,但是在这里由构造函数的prototype指向的原型对象变成了现有的对象,不是构造函数本省的原型对象,因此让它的constructor重新只回来,指向构造函数,这也是原型链的原理来张图片:

捕获.PNG

所以要添加如下的方法:

//解决:重新赋值成对应的构造函数
Person.prototype.constructor = Person;

var per = new Person("sunck", 18);
console.log(per.constructor);
console.log(Person.prototype.constructor);

结果:

捕获.PNG

实例化对象

var per1 = new Person("sunck", 18);
        console.log(per1.name);
        console.log(per1.age);
        per1.say();

        console.log(per1.height);
        console.log(per1.weight);
        per1.run();

结果:

捕获.PNG

发现实例化的对象可以访问原型对象中的属性和方法,可以发现原型对象可以为对象添加属性和方法。

3.使用原型的方法与属性

上一个方法主要讲了用原型设置属性和方法,既然能设置,那么肯定能访问,我们来看一下。
还是上面的代码:

//访问自身属性与方法
console.log(per.name);
console.log(per.age);
per.say();

结果:


捕获.PNG

当前对象访问原型对象中的属性(访问原型属性):
访问原型属性的方式与访问自身属性的方式是一样的。
对象访问属性的原理:当我们访问name属性时,首先在自身属性中查找,找到了立即返回当前属性的值。当我们访问height属性时,也会先在自身属性中查找,找不到的话去它的原型对象中查找,找到就返回数值。如果找不到还会去上一级原型对象中查找,最终找不到反返回undefined。

console.log(per.height);
        console.log(per.constructor.prototype.height);
        per.run();

结果:

捕获.PNG
我们来总结一下:
原型对象的精髓:实时性;在JS中,对象的传递都是引用传递,对于同一个构造函数创建的对象来说,仅仅是拥有一个原型对象的引用,不会拥有原型对象的副本。如:
Person.prototype.eat = function() {
    console.log("eat");
};
per.eat();

结果:

捕获.PNG
在上面的代码,你发现了什么?在构造函数中没有eat()这个函数,于是在原型对象上我们添加了一个eat()方法;per对象是在添加eat()方法之前就被创建了,但是它还是能访问后来创建的eat()函数,这就是原型对象的精髓——实时性

4.利用自身属性重写原型属性——hasOwnProperty()与isPrototypeOf()方法

这个知识点主要是介绍hasOwnProperty()与isPrototypeOf()这两个方法。可能上代码更能直观点:

var base = {
            height: 180,
            weight:70,
        };

        function Person(name, age){
            this.name = name;
            this.age  = age;
            this.height = 175;
            this.say = function(){
                console.log("My name is " + this.name);
            };
        }


        //
        Person.prototype = base;
        Person.prototype.constructor = Person;
        console.log(base.constructor);


        var per = new Person("sunck", 18);
        console.log(per.constructor);
        console.log(per.height);

在这扯个题外话:访问height属性,是自身属性还是原型属性呢?再上一个知识点说到,现在滋生属性上找,没有找到的话就到原型对象上找。所以这是——自身属性
结果:

捕获.PNG
看见 console.log(per.height);打印出来的是自身属性。
hasOwnProperty():判断属性是否是自身属性;自身属性返回true,原型属性返回false
console.log(per.hasOwnProperty("weight"));

结果:

捕获.PNG

删除与原型属性同名的height属性,那么原型属性暴露出来

delete per.height;
console.log(per.height);

isPrototypeOf():判断一个对象是否是另一个对象的原型对象

console.log(base.isPrototypeOf(per));
        console.log(new Array(5).isPrototypeOf(per));

结果:

5.for-in枚举属性(propertyIsEnumerable()方法)

var base = {
            height: 180,
            weight:70,
        };
        function Person(name, age){
            this.name = name;
            this.age  = age;
            this.say = function(){
                console.log("My name is " + this.name);
            };
        }
        Person.prototype = base;
        // Person.prototype.constructor = Person;



        var per = new Person();

        for(var i in per){
            console.log(i);
        }

结果:


捕获.PNG

总结一下:
1.不是所有的属性都能遍历出来,比方说数组中的length和constructor。自身属性与原型属性(原型链上的属性)都可以遍历。
2.內建属性,对象自身自带的属性。內建属性大多数都是不可以枚举的。
3.propertyIsEnumerable判断属性是不是可枚举的,原型属性都会返回false。

console.log(per.propertyIsEnumerable("name"));
console.log(per.propertyIsEnumerable("height"));
console.log(per.propertyIsEnumerable("constructor"));
console.log(new Array(5).propertyIsEnumerable("length"));

结果:


捕获.PNG

6.总结

   这一节的原型对象我自认为说的还算通畅吧,如果又不懂得地方欢迎来信哦!!!

相关文章

  • JavaScript难点——原型对象及其方法

    0.前言 最近在网上学习原型这一块,看了很多博客,都不尽人意,因此笔者自己写一篇文章,尽量让大家明白这是怎么一回事...

  • JS原型链

    javaScript原型链 JavaScript所有对象都有原型,当对象有属性或方法调用的时候,对象就会从自身查找...

  • Javascript-原型与原型链

    简单介绍 JavaScript 每个对象都拥有一个原型对象,对象以其原型为模板从原型中继承方法和属性; 原型对象也...

  • 原型和原型链

    原型 javascript中每个JS对象一定对应一个原型对象,并从通过proto属性原型对象继承方法和属性 jav...

  • JavaScript Class 完全指南

    JavaScript 使用原型继承:每个对象都从原型对象继承属性和方法。 Java 或 Swift 等语言中作为创...

  • 原型、原型链

    理解JavaScript原型 彻底理解JavaScript原型 原型 原型是一个对象,所有对象都可以成为原型,其...

  • JavaScript——创建对象的五种方式分析(工厂模式 原型

    首先明确JavaScript中的方法分为3类 ——类方法,对象方法,原型方法,创建对象关键在定义方法JavaScr...

  • javascript的方法

    1. javascript的方法可以分为三类: a 类方法;b 对象方法;c 原型方法 例子: //对象方法 fu...

  • javascript原型链图解

    javascript原型链图解函数对象及其 prototype 属性函数的所有实例中的__proto__属性都指向...

  • JavaScript难点之原型和原型链

    这篇文章主要是学习一下JavaScript中的难点------原型和原型链 自定义一个对象 我们学习一门编程语言,...

网友评论

    本文标题:JavaScript难点——原型对象及其方法

    本文链接:https://www.haomeiwen.com/subject/nsyxbttx.html