002构造函数与原型


002

主要熟悉代码的逻辑,ES6中都是使用class代替构造函数加原型对象的方式


一、构造函数

ES6之前没有类的概念,需要使用构造函数来进行面向对象的编程,使用function来初始化对象,可以把对象中的一些公共的属性和方法抽取出来,封装到函数中,在使用new关键字进行实例化。

1.静态成员和实例成员

实例成员可以看成是构造函数定义时声明的成员,需进行实例化之后,使用m.xxx来访问;静态成员是在构造函数本身添加的成员,需要动态的添加,只能通过Student.xxx来调用。

//构造函数
    function Student(){
        this.name = '张三';
        this.age = '12';
        this.learning = function (){
            console.log('热爱学习');
        }
    }
    //实例化
    var m = new Student();
    //访问实例成员
    console.log(m.name);
    //添加静态成员
    Student.sex = '男';
    //访问静态成员
    console.log(Student.sex);

2.构造函数的缺陷

每实例化一个对象就,对象中的方法会单独开辟一个内存空间,资源浪费。因此就需要构造函数原型。

一、原型对象与原型链

1.构造函数原型prototype

每个构造函数中都存在一个原型属性,其本质就是一个对象。
通过把函数体添加至原型对象中,实现每实例化一个对象,共用一个函数,这样就避免了上述的缺陷

Student.prototype.learning = function (){
        console.log('热爱学习');
    }

此外,之所以可以使用原型对象中的方法,是因为实例化一个对象之后,在其中自动添加了一个__proto__(称为对象原型)的属性,其指向构造函数中的原型对象,即这里m.__proto__和Student.prototype是等价的。

2.constructor构造函数

上面的m.__proto__和Student.prototype中都有一个constructor,含义是表征原型对象和对象原型是由哪一个构造函数衍生出来的,打印m.proto.constructor即返回最开始创建的那个构造函数。
为了格式完整,往往使用下面的方式创建原型对象:

Student.prototype = {
        constructor: Student,
        learning: function (){
            console.log('热爱学习');
        },
        reading: function (){
            console.log('喜欢读书');
        }
    }

因为是prototype等于一个对象,这把原来的值覆盖掉了,因此需要加一句constructor: Student,来指向构造函数。

3.“套娃”(原型链)

原型对象本身也是一个对象,其内部也有一个对象原型__proto__,其指向Object原型对象,Object对象通过constructor指向Object构造函数,Object原型对象内也有一个__proto__,指向为null。上述即为原型链
图片来源于黑马程序员的视频教程,ldh对象实例等价于上面的m对象实例

4.对象成员查找规则

对象实例→原型对象→Object对象→null,若都有则采取就近原则,使用前一级的方法

5.用原型对象扩展内置对象方法

实际开发中不会用到,可以看看里边的逻辑

Array.prototype.square_sum = function (){
        var sum = 0;
        for (var i=0;i<this.length;i++){
            sum += this[i]*this[i];
        }//this指向调用该方法的实例对象
        return sum;
    }

三、继承

1.call()

使用格式function.call(this指向,参数1,参数2…)

function fn(x,y){
        console.log(x+y);
        console.log(this);
    }
    var o = {
        name: 'andy'
    };
    fn(1,2)
    fn.call(o,1,2);

2.借用父构造函数继承属性

主要需要使用call方法改变函数的指向

function Father(fname, fage){
        this.name = fname;
        this.age = fage;
    }

    function Son(sname, sage){
        Father.call(this, sname, sage);
    }
    var s = new Son("ZRJ",18);
    console.log(s.age);

3.借用新建实例继承方法

function Father(fname, fage){
        this.name = fname;
        this.age = fage;
    }
    Father.prototype.money = function (){
        console.log('可以挣钱');
    }
    function Son(sname, sage){
        Father.call(this, sname, sage);
    }
    Son.prototype = new Father();//相当于新开辟了一个地址空间,因此不会影响父构造函数的原型对象
    Son.prototype.constructor = Son;//由于上面改变了指向,需要使用constructor进行重新指向
    var s = new Son('ZRJ',19);
    s.money();

4.ES6=>类

ES5基于构造函数加原型对象进行面向对象的编程,ES6中使用类(语法糖),其本质还是一个函数,类中也有原型对象、原型对象中有constructor指向类本身…,新的class写法只是让对象原型的写法更加清晰、更具面向对象的特点。

三、ES5的新增方法

1.数组方法:forEach(), filter(), some()

感觉forEach()主要用来渲染界面,filter()用来筛选,用的比较多

var arr = [2,2,3];

    //forEach()
    //a代表每一个元素的值、b代表每一个元素的索引号、c代表数组本身
    arr.forEach(function (a, b, c){

    })

    //filter()
    //用于数组的筛选,参数同上,return加返回条件,返回的是一个数组
    var newArr = arr.filter(function (a, b, c){
        return a >= 3;
    })

    //some()
    //查找数组中是否有满足条件的元素,返回一个布尔值,找到即终止
    var result = arr.some(function (value, index, array){
        return value === 2;
    })

2.字符串方法:trim()

var str = '    123    ';
var newStr = str.trim();

3.对象方法:Object.defineProperty()

Object.defineProperties(obj, 'name', {
        value: 'zzrrjj',//改变属性的值,若没有则为添加属性
        writable: true,//设置属性是否可重写,默认false
        enumerable: true,//设置是否是可被枚举,默认false
        configurable: true//设置属性是否可被删除以及是否可被再次修改特性,默认false
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值