JS中构造函数的原型prototype

    科技2024-07-14  74

    来来来,JavaScript核心基础语句送给你们 学JS你不会DOM算真的学会了吗? 对JavaScript中的 事件 进行疯狂 处理 用BOM来实现轮播图效果 我们来实现创建JavaScript中的自定义对象 JS中构造函数的原型prototype 还不明白JS中的内置对象吗? 快来这里! JavaScript中数据如何存储在客户端?带你看看Cookie和WebStorage

    原型prototypr

    1. 简介

    在构造函数中有一个属性叫prototype

    prototype是一个对象属性,其属性值为对象,称为原型对象可以通过prototype来添加新的属性和方法,此时所有该构造函数创建的对象都会具有这些属性和方法由该构造函数创建的对象会默认链接到该属性上

    语法:

    构造函数.prototype.属性名 = 值;构造函数.prototype.方法名 = function(){定义方法体};

    访问对象属性的查找顺序:

    首先在当前对象中查找对应的实例对象如果没有,就会到该对象关联的构造函数的prototype属性中查找,即到原型对象中查找

    作用:

    对象间共享数据为“类”(系统内置或自定义)增加新的属性、方法,并且新增内容对于当前页面中已经创建的而对象也由效 <script> //定义一个构造函数Student function Student(name,age){ this.name = name; //实例属性,每个实例都具有一个独立的该属性 this.age = age; this.show = funciton(){ //实例方法,每个对象都具有一个独立的该方法 console.log('我叫'+this.name+'年龄'+this.age); } /* this.sayhello = function(){ console.log('您好'); } this.sayDoodbye = function(){ console.log('再见'); } */ } //构造函数中存在一个名为prototype的属性 //console.log(Student.prototype); //通过为构造函数的prototype添加属性和方法,从而让所有该构造函数创建的对象都能共享这些属性和方法 this.sayhello = function(){ //原型方法 console.log('您好'); } this.sayDoodbye = function(){ console.log('再见'); } Student.prototype.class = '三年级二班'; //原型属性,所有对象共享的原型对象class //创建对象 var stu1 = new Student('tom',26); stu1.class = '三年级一班'; //为stu1添加一个实例对象class console.log(stu1.name,stu1.age,stu1.calss); stu1.show(); stu1.sayhello(); stu1.sayGoodbye(); var stu2 = new Student('alice',22); console.log(stu2.name,stu2.age,stu.class); stu2.show(); stu2.sayhello(); stu2.sayGoodbye(); //stu1.sayhello()、sayGoodbye()和stu2.sayhello()、sayGoodbye()分别使用不同的内存空间,都要占用资源,但其内容完全相同,为了节省内存空间,希望能够公用。 console.log(stu1 === stu2); console.log(stu1.name === stu2.name); console.log(stu1.show === stu2.show); console.log(stu1.sayhello === stu2.sayhello ); console.log(stu1.sayGoodbye === stu2.sayGoodbye); //扩展Array var names = new Array('tom','jack','alice','mike','alex'); //names.sort(); //names.reverse(); //names.join('-'); //为Array类型添加显得功能(属性或方法) Array.prototype.sortReverseJoin = function(){ console.log(this); //this表示当前对象,即将来要操作的数组 this.sort(); this.reverse(); var str = this.join('-'); console.log(str); } console.log(Array.prototype); var hobbies = ['eat','sleep','play','study']; names.sortReverseJoin(); bobbies.sortReverseJoin(); </script>

    2. _ _ proto _ _(前后双下划线)

    prototype是一个隐藏属性,于是为每个对象那个提供一个叫__proto__的属性

    对象的__proto__与创建它的构造函数的prototype本质上是同一个东西__proto__是对象的属性,是站在对象的角度,来讨论其原型对象prototype是构造函数的属性,是站在构造函数的角度,来讨论其原型对象由于__proto__是非标准属性,因此一般不建议使用 <script> function Student(name){ this.name = name; this.show = function(){ console.log('我叫'+this.name); } } Student.prototype.sayhello = function(){ console.log('你好'); } //构造函数的prototype属性 //console.log(Student.prototype); //stu会自动链接到其构造函数的prototype属性上 var stu = new Student('tom'); //stu.sayhello(); console.log(stu); console.log(stu.__proto__); //__proto__是对象的属性,是站在对象的角度,来讨论其原型对象 console.log(Student.prototype); //prototype是构造函数的属性,是站在构造函数的角度,来讨论其原型对象 console.log(stu.__proto__ === Student.prototype); //由于__proto__是非标准属性,因此一般不建议使用 //stu.__proto__.sayhello(); stu.sayhello(); </script>

    3. 对象的类型

    判断数据的类型:

    使用typeof

    可以判断任意变量的类型 判断对象的类型时总是返回object

    使用instanceof

    只能判断对象是否为某种类型,需要指定判断的目标数据类型,无法获取对象的类型名称 语法:对象 instanceof 数据类型,返回boolean值

    获取对象的类型:

    函数有一个name属性,通过该属性可以获取函数的名称构造函数的名称就是对象的名称 var stu = new Student() ------->Student类型 var p = new Person() ------->Person类型 var nums = new Array() -------->Array类型 var obj = new Object() ------->Object类型 function Student(){}; function Teacher(){}; var obj1 = new Object(); var obj2 = new Array(); var obj3 = new Student(); var obj4 = new Teacher(); //typeof只能判断简单的数据类型,判断对象的类型时总是返回object //console.log(typeof obj1); //console.log(typeof obj2); //console.log(typeof obj3); //console.log(typeof obj4); //instanceof用来判断对象的类型,判断对象是否为某种类型,返回boolean console.log(obj1 instanceof Object); console.log(obj2 instanceof Array); console.log(obj3 instanceof Student); console.log(obj4 instanceof Teacher); //结论:构造函数的名称就是对象的类型名

    4. constructor属性

    每个对象都有一个constructor属性,该属性描述的就是其构造函数。

    对象的constructor属性是原型对象提供的,因为每个对象都链接到其原型对象上。

    如果想要获取一个对象的构造函数的名字,我们就可以使用constructor属性和name属性

    //运用上面例子中创建的对象 console.log(obj3.constructor.name); //通过构造函数的name属性,获取构造函数的名称

    5. call()方法和apply()方法

    作用:以某个对象的身份来调用另一个对象的方法

    区别:传参的方式不同

    第一个参数是相同的,都是表示由该对象来调用执行

    后面的参数不同

    call是逐个传参,后面参数可以有多个,逗号隔开 apply是以数组形式传参,后面参数只能有一个,会自动拆分为多个元素传入

    //定义一个对象,包含属性和方法 var stu = { name:'tom', age:18, study:function(){ console.log('我叫'+this.name+',年龄:'this.age); } } //stu.study(); //调用对象的方法 function run(){ console.log('跑步'); } run(); //window直接调用函数 /** * 如果stu想要调用run()方法,怎么办? */ //方式一:为stu添加run()方法,永久添加 stu.run = run; //为stu添加run()方法,指向run()函数 stu.run(); //方式二:只想临时调用(注意这里的写法) run.call(stu); //以stu对象的身份来调用run()函数 run.apply(stu); //此处两个函数能实现相同的功能 //this的转变 window.run(); //直接调用,此时的this表示window run.call(stu); //对象临时调用,此时的this表示调用的对象,即stu,称为对象冒充 /** * call()和apply()的区别 */ function calc(a,b,c){ console.log(a+b+c); } calc.call(stu,1,2,3); //逐个传参 calc.apply(stu,[1,2,3]); //数组形式传参,只能传一个参数 /** * 应用场景 */ //在stu对象中添加一个属性 stu.sex = 'male'; //直接添加 Array.prototype.push.call(stu,'male'); //通过push()方法添加 Array.prototype.push.call(stu,'hobby'); //Object.prototype.toString()方法,用来判断值的类型 console.log(Object.prototype.toString.call('hello')); console.log(Object.prototype.toString.call(true)); console.log(Object.prototype.toString.call(undefined)); console.log(Object.prototype.toString.call(null)); console.log(Object.prototype.toString.call(new Array()));

    6.继承

    JS实现继承的三种方式:

    对象冒充继承,也称为构造继承

    核心:使用call,以对象冒充的形式调用父类的构造函数,相当于是复制父类的实例属性给子类

    缺点:只能继承父类构造函数中的属性和方法,无法继承原型中的属性和方法

    原型链继承

    核心:使用prototype,将父类的实例作为子类的原型

    缺点:创建子类实例时,无法向父类构造函数传参,导致继承的父类属性没有值

    组合继承

    对象冒充+原型链

    function Person(name,age){ this.name = name; this.age = age; this.run = function(){ console.log('跑步'); } } Person.prototype.sex = 'male'; Person.prototype.show = function(){ console.log('我叫'+this.name+',年龄:'+this.age+',性别:'+this.sex); } /** * 方式1:对象冒充继承,也称为构造函数 */ function Student(name,age){ Person.call(this,name,age); //此处Person中的this指向的是将来创建的Student对象 } var stu = new Student('tom',20); //可以继承父类构造函数中的属性和方法 console.log(stu.name,stu.age); stu.run(); //无法继承父类原型中的属性和方法 console.log(stu.sex); stu.show; /** * 方式2:原型链继承 */ function Student(name,age){} Student.prototype = new Person(); //将Student原型链指向Person对象,从而继承Person console.log(Student.prototype); var stu = new Student('tom',20); console.log(stu.name,stu.age); //name和age属性都是undefined,无法获得父类对象的属性 stu.run(); console.log(stu.sex); stu.show(); /** * 方式3:组合继承(对象冒充+原型链) */ function Student(name,age){ Person.call(this,name,age); //对象冒充 } //(1)调用两次父类的构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了,所以性能稍差一点) Student.prototype = new Person(); //(2)将Student原型指向Person原型 Student.prototype = Person.prototype; var stu = new Student('tom',20); console.log(stu); </script>

    7. 原型链

    任何对象都有其原型对象,原型对象也有原型对象,对象的原型对象一直往上找,直到null为止。

    在这一过程中,有一个Object类型的对象,它就是Object prototype位于顶层。

    /** * nums对象的原型链 * nums——>Array.prototype——>Object.prototype——>null * nums.__porto__与Array.prototype是同样的 */ var nums = new Arrray(12,43,5,3,8); nums.push(24); nums.reverse(); console.log(nums); /** * stu对象的原型链结构 * stu——>Student.prototype——>Object.prototype——>null * stu.__prototype__与Student.prototype是同样的 */ function Student(name){ this.name = name; } Student.prototype.sex = 'male'; var stu = new Student('tom'); console.log(stu); //Object的原型链结构 var o1 = new Object(); console.log(o1); //创建对象 console.log(Object.prototype); //对象的原型,站在构造函数的角度 console.log(o1.__proto__); //对象的原型,站在对象的角度 console.log(Object.prototype.constructor); //构造函数
    Processed: 0.011, SQL: 9