当前位置: 首页 > Web前端 > HTML

ES5的构造函数原型链继承了

时间:2023-04-02 13:52:14 HTML

constructor构造函数,这是一个专门用来生成实例对象的函数。构造函数可以生成多个实例对象,所有实例对象都具有相同的结构。functionPerson(name){this.name=name;}为了区别于普通函数,构造函数名的首字母通常大写。构造函数有两个特点:函数体内部使用了this关键字,表示要生成的对象实例。创建对象时,必须使用new命令。new命令的基本用法new命令的作用是执行构造函数并返回一个实例对象。leta=newPerson('dora');a.name//doranew命令本身可以执行构造函数,所以后面的构造函数可以带括号也可以不带括号,但是为了表明是函数调用,所以是建议使用括号表示更明确的语义。new命令的原理在使用new命令时,其背后的函数依次执行以下步骤:创建一个空对象作为要返回的对象实例。让o=新对象();将这个空对象的原型指向构造函数的原型属性。Object.setPrototypeOf(o,Foo.prototype);将构造函数的this绑定到新创建的空对象。Foo.call(o);开始执行构造函数内部的代码。如果构造函数内部有return语句,后面跟着一个对象,new命令会返回return语句指定的对象;否则不管return语句都会返回this对象,return后面的语句不会执行。函数Person(name){this.name=name;如果(名称==未定义){返回{};}elseif(typeofname!='string'){return'nameiswrong';}console.log(111);}newPerson();//{}新人(123);//{name:123}newPerson('dora');//{name:'dora'}//111new.target如果当前函数被new命令调用,函数内部的new.target属性指向当前函数,否则未定义。functionF(){console.log(new.target===F);}F()//falsenewF()//true使用这个属性,可以判断调用函数时是否使用新命令。functionF(){if(!new.target){thrownewError('请使用新命令调用!');}}F()//falsenewF()//true强制使用新命令如果不使用新命令执行构造函数会导致一些意想不到的结果,所以为了保证必须使用构造函数配合new命令,除了new.target还有以下两种解决方案。1.在构造函数内部使用严格模式在构造函数内部的第一行添加usestrict。这样的话,一旦忘记使用new命令,直接调用构造函数就会报错。功能人(姓名,年龄){'使用严格';this.name=名称;this.age=age;}Person()//TypeError:Cannotsetproperty'name'ofundefined错误原因是调用构造函数时没有添加new使用函数时,this指向全局对象,但是在严格模式下,this不能指向全局对象,默认等于undefined。给undefined添加属性肯定会报错。2.在构造函数内部使用instanceof判断是否使用new命令}这个名字=名字;this.age=age;}Person('dora',18).name//dora(newPerson('dora',18)).age//18判断this是否是构造函数内部的实例,如果不是,那就直接返回一个实例对象。prototypeprototype任何函数都有一个prototype属性,这个属性称为函数的“原型”,属性值是一个对象。只有函数具有原型属性。functionf(){}typeoff.prototype//“对象”对于普??通函数的原型没有用处。但是对于构造函数来说,当通过new生成实例时,这个属性会自动成为实例对象的原型对象。原型属性的作用是定义所有实例对象共享的属性和方法。如果把对象的方法写进构造函数,有多少实例是new的,这个方法会被复制多少次。复制的函数虽然相同,但是指向不同的引用地址,不利于函数的复用。functionPerson(){this.name=function(){console.log('dora');}}letp1=newPerson();letp2=newPerson();p1.name===p2.name//false因此,所有的属性都定义在构造函数中,所有的方法都定义在原型中构造函数。这样实例的方法都指向同一个引用地址,内存消耗小很多。constructor属性函数prototype原型对象的属性,指向原型所在的构造函数,可以被所有实例对象继承,指向构造自身的构造函数。Person.prototype.constructor.name//"Person"p1.constructor.name//"Person"函数的name属性返回函数名。为原型添加属性1.点语法添加属性Person.prototype.sayHi=function(){console.log('Hi,IamDora');}2.覆盖原型对象Person.prototype={sayHi:function(){console.log('嗨,我是朵拉');}}这种方式直接用对象字面量覆盖会导致构造函数与构造函数失去联系,可以手动添加这个属性。Person.prototype={constructor:Person,sayHi:function(){console.log('嗨,我是朵拉');}}3.添加Object.assign(Person.prototype,{sayHi:function(){}})在构造函数原型中定义方法时,尽量不要相互嵌套,每个方法之间要相互独立。_proto_原型对象任何对象都有一个__proto__属性,称为对象的“原型对象”,对象的原型对象就是其构造函数的原型。functionPerson(){}letp1=newPerson();p1.__proto__===Person.prototype//trueObject.getPrototypeOf(obj)__proto__不是语言本身的属性,而是各大浏览器厂商添加的私有属性,虽然很多浏览器都可以识别这个属性,但是还是不建议在生产环境中使用,以免对环境产生依赖。在生产环境中,我们可以使用Object.getPrototypeOf(obj)方法来获取参数对象的原型。Object.getPrototypeOf(p1)===Person.prototype//真正的原型链机制当访问一个对象的属性时,如果该对象没有这个属性,系统会寻找该对象的__proto__原型对象,即也是一个对象。它也有自己的__proto__原型对象,然后它会依次向上查找原型链,直到原型链的末尾Object.prototype。Object()是系统内置的构造函数,用于创建对象,Object.prototype是所有对象原型链的顶端,Object.prototype的原型对象为null。Object.getPrototypeOf(Object.prototype)//null如果对象本身和它的原型都定义了一个同名的属性,那么首先读取对象本身的属性。继承的核心是子类构造函数的原型是父类构造函数的实例对象。首先继承父类的属性//1.父类构造函数Super(data){this.data=data;};Super.prototype.funName=function(){};//2.子类构造函数Sub(){//用于继承父类的参数和属性Super.apply(this,arguments);}其次,整体继承父类的方法继承Sub.prototype=Object.create(Super.原型);//或Sub.prototype=newSuper();单一方法的继承Sub.prototype.funName=function(){Super.prototype.funName.call(this);//其他一些代码}最后,此时需要将构造函数改为指向子类实例的构造函数需要手动更改父类构造函数Super。Sub.prototype.constructor=Sub;多重继承ES5没有多重继承功能,即不允许一个对象同时继承多个对象,但是这个功能可以通过变通的方式来实现。函数S(){M1.call(this);M2.call(this);};S.prototype=Object.create(M1.prototype);//继承M1Object.assign(S.prototype,M2.prototype);//添加M2S.prototype.constructor=S到继承链;//指定构造函数。实例验证instanceof运算符instanceof运算符返回一个布尔值,指示对象是否是构造函数的实例。继承的子类实例也是父类的实例,所以继承也是如此。letd=newDate();dinstanceofDate//truedinstanceofObject//trueObject.prototype.isPrototypeOf()实例对象可以继承isProtorypeOf()方法判断对象是否为参数对象的原型对象。只要实例对象在参数对象的原型链上,isPrototypeOf()方法就返回true。leto1={};leto2=Object.create(o1);leto3=Object.create(o2);o2.isPrototypeOf(o3)//trueo1.isPrototypeOf(o3)//trueo2.isPrototypeOf(o2)//错误的