Javascript漂流记(上)__原型、原型链、toString、call/apply

版权声明:本文为博主原创,转载请附上博文链接。 https://blog.csdn.net/AquamanTrident/article/details/90581229

一、原型:是function对象的一个属性,是构造函数制造出对象的公共祖先。通过该构造函数产生的对象,可以继承原型的属性和方法。原型也是对象。
    
       提取公有属性:

        //Person.prototype = {},生来就有,是person1,person2...的爹
        Person.prototype = {
            //constructor : Person,
            lastName : 'James',
            firstName : 'Lebron',
            gender : 'male',
            age : 36
        }
        function Person(club,score){
            //var this = {
            //    __proto__ : Person.prototype(在person1访问属性时,如果自己身上没有,就会沿着__proto__的指向去找)      
            //}
            this.club = club;
            this.score = score;
            //return this;
        }
        var person1 = new Person('Laker', 10000);
        var person2 = new Person('Heat', 8000);

        增:Person.prototype.wife = 'Laurel';
        删:delete Person.prototype.lastName; 从person1下手是删不掉
        改:Person.prototype.lastName = 'King'; 在person1身上是改不掉的,除非是引用值的调用式修改,详情看下文。
        查:person1.lastName;
        Person.prototype生来有constructor属性,指向Person(),可以手动更改。
        其中person1可以通过person1.constructor找到构造它的函数Person()。


二、原型链:

        //Grand.prototype.__proto__ = Object.prototype
        //Grand.prototype.lastName = 'James';
        function Grand(){}
        var grand = new Grand();

        Father.prototype = grand;
        function Father(){
            this.fisrtName = 'Lebron';
            this.club = {
                no1 : 'Heat',
                no2 : 'Laker'
            }
        }
        var father = new Father();
    
        Son.prototype = father;
        function Son(){
            this.hobbit = 'basketball';
        }
        var son= new Son();

       增删改查,类似原型增删改查
       说到其中的改:son.club.no3 = 'Rocket'; 可以实现引用值的调用式修改。


       1、另一种构造对象的方式:

            var obj = Object.create(原型)

            绝大多数对象的最终都会继承自Object.prototype(Object.create(null)是个例外)。

       2、关于toString(),观察下列代码输出。

            Object.prototype上本身含有toString方法,但输出形式是"[object Xxxxx]",为何数字,字符串,数组,布尔会输出不同形式?

        123.toString();//会报错,首先识别成浮点型

        var num = 123;
        num.toString();    //返回"123"

        var str = 'abc';
        str.toString();    //返回"abc"

        var arr = [1,2];
        arr.toString();    //返回"1,2"

        var obj = {};
        obj.toString();    //返回"[object Object]"

       拿数字举例,尽管Number.prototype.__proto__ = Object.prototype。但Number.prototype上有重写的toString方法,并不会调用Object.prototype本身的方法。同样:
        String.prototype上有重写的toString方法
        Array.prototype上有重写的toString方法
        Boolean.prototype上有重写的toString方法

        如何来证明呢?还记得初学JavaScript使用过的document.write。我们来看一下它的底层原理。

        var obj = Object.create(null);
        document.write(obj);//会报错
        var obj = Object.create(null);
        //因为此时的obj对象没有prototype,也不存在toString方法,我们为其手动添加。
        obj.toString = function(){
	        return '呵呵呵';
        }
        document.write(obj);//打印结果为呵呵呵。证明调用的是toString

         3、JavaScript小bug:0.14 * 100 = 14.000000000000002
               是由于JavaScript精度不准造成的,正常计算的范围是小数点前后各16位。我们应该尽量避免小数操作,如果不能避免,可以使用Math.floor/Math.ceil。

三、call和apply,改变this指向,传参列表不同

        function Person(name, age, gender){
            //this == obj
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        var person = new Person('James', 36, 'male');
        var obj = {};
        //Person(); === Person.call();
        Person.call(obj, 'Lau', 128, 'male');

       在开发过程中,想用别人的方法实现自己的功能怎么办,还用说,call它啊,参数第一位把填自己的对象。
       如下列代码,想要借用上图Person的方法来实现自己的功能,可按照下列操作。

        function Student(tel, grade){
            //var this = {__proto__ : Student.prototype}
            Person.call(this, name, age, gender);
            this.tel = tel;
            this.grade = grade;
        }
        var student = new Student('Jack', 128, 'male', 17600001234, 2019);

        call和apply的唯一不同之处在于传参列表,apply的传参形式为arguments。

以上内容属二哥原创,整理自 "渡一教育Javascript课程" ,一个值得推荐的"渡一教育"。

猜你喜欢

转载自blog.csdn.net/AquamanTrident/article/details/90581229