一面二面(4)之JavaScript面向对象

    技术2025-12-19  8

    一、面向对象基本特征: 1.封装:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 2.继承:通过继承创建的新类称为“子类”或“派生类”。继承的过程,就是从一般到特殊的过程。 3.多态:对象的多功能,多方法,一个方法多种表现形式。 4.Javascript是一种基于对象(object-based)的语言。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)—–es6以前是这样的。所以es5只有使用函数模拟的面向对象。

    二.创建对象方法: 1.字面量: var obj = { name:“nieli”} 2.构造函数: var M = function () { this.name = ‘nieli’} var obj = new M() 3.ES5: var P = { name:‘nieli’ } var obj = Object.create§

    三.原型/构造函数/实例/原型链: 原型链的精髓:不同实例同一个构造函数,更改构造函数的原型可以使得不同实例同时受影响 对象实例化方式: 1.工厂模式:

    function createCar(color,wheel){//createCar工厂 var obj = new Object;//或obj = {} 原材料阶段 obj.color = color;//加工 obj.wheel = wheel;//加工 return obj;//输出产品 } //实例化 var cat1 = createCar("红色","4"); var cat2 = createCar("蓝色","4"); alert(cat1.color);//红色

    2.构造函数模式:为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。 所谓”构造函数”,其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。加new执行的函数构造内部变化:自动生成一个对象,this指向这个新创建的对象,函数自动返回这个新创建的对象

    function CreateCar(color,wheel){//构造函数首字母大写 //不需要自己创建对象了 this.color = color;//添加属性,this指向构造函数的实例对象 this.wheel = wheel;//添加属性 //不需要自己return了 } //实例化 var cat1 = new CreateCar("红色","4"); var cat2 = new CreateCar("蓝色","4"); alert(cat1.color);//红色

    3.构造函数注意事项:

    1.此时CreateCar称之为构造函数,也可以称之类,构造函数就是类 。 cat1,cat2均为CreateCar的实例对象。 2.CreateCar构造函数中this指向CreateCar实例对象即 new CreateCar( )出来的对象。 3.必须带new 。 4.构造函数首字母大写,这是规范,官方都遵循这一个规范,如Number() Array()。 5.contructor:这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数,即CreateCar。

    alert(cat1.constructor == CreateCar); //true alert(cat2.constructor == CreateCar); //true

    7.每定义一个函数,这个函数就有一个 prototype 的属性{},proto 指向被实例化的构造函数的prototype,prototype默认带constructor属性,constructor指向构造函数。 8.instanceof 运算符:object instanceof constructor运算符,验证构造函数与实例对象之间的关系。

    alert(cat1 instanceof CreateCar ); //true alert(cat2 instanceof CreateCar ); //true

    9.构造函数的问题: 构造函数方法很好用,但是存在一个浪费内存的问题。如果现在为其再添加一个方法showWheel。那么,CreateCar就变成了下面这样,这样做有一个很大的弊端,对于每一个实例对象,showWheel都是一模一样的内容,每一次生成一个实例,都必须生成重复的内容,多占用一些内存。这样既不环保,也缺乏效率。

    10.Prototype 原型: Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。 这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。__proto__是原型链,指向实例化的函数原型。

    function CreateCar(color,wheel){ //属性写构造函数里面 this.color = color; this.wheel = wheel; } //方法写原型里面 CreateCar.prototype.showWheel = function(){ alert(this.wheel); } CreateCar.prototype.showName = function(){ alert('车'); } //生成实例。 var cat1 = new CreateCar("红色","4"); var cat2 = new CreateCar("蓝色","4"); cat1.showName();//'车' //这时所有实例的showWheel属性和showName方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。 alert(cat1.showWheel == cat2.showWheel );//true alert(cat1.showName == cat2.showName );//true console.log(cat1.__proto__ === CreateCar.prototype); //true

    11.静态方法和静态属性:只属于类而不属于实例化对象

    function foo(){ this.show = function(){ return this; } } foo.test = 123; //静态属性 foo.say = function(){ return this; } foo.say(); var fn = new foo(); //实例化的新的对象,this指向这个新的对象,不能访问类的静态方法 fn.say(); //Noname1.html:45 Uncaught TypeError: fn.say is not a function console.log(foo.say() == fn.say());

    12.instanceof的原理: 四:对象继承 1.构造函数继承:

    function Parent(){this.name='nieli'} function Child(){Parent.call(this);this.type = 'child'},

    缺点:部分继承:无继承Parent的原型,只是继承了Parent的属性 2.借助原型链加构造函数的继承,共用一个父原型:

    function Parent(){this.name='nieli';this.play=[1,2,3]} function Child(){this.type = 'child'}Child.prototype = new Parent(); var s1 = new Child(); var s2 = new Child(); s1.play.push(4) console.log(s1.play,s2.play)

    缺点:实例出来的对象,之间的构造函数是一样的,改变一个实例的原型属性,另一个实例的属性页发生变化 3.优化组合(1)

    function Parent(){this.name='nieli';this.play=[1,2,3]} function Child(){Parent.call(this);this.type = 'child'} Child.prototype = new Parent(); var s1 = new Child(); var s2 = new Child(); s1.play.push(4) console.log(s1.play,s2.play)

    4.优化组合(2):

    function Parent(){this.name='nieli';this.play=[1,2,3]} function Child(){Parent.call(this);this.type = 'child'} Child.prototype = Parent.prototype; var s1 = new Child(); var s2 = new Child(); console.log(s1,s2) console.log(s1 instanceof Child, s1 instanceof Parent ); console.log(s1.constructor)

    5.优化组合(3):

    function Parent(){this.name='nieli';this.play=[1,2,3]} function Child(){Parent.call(this);this.type = 'child'} Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; var s1 = new Child(); console.log(s1 instanceof Child, s1 instanceof Parent ); console.log(s1.constructor)

    五.多态: 同一个方法,面对不同的对象有不同的表现形式就叫做多态。

    var obj = { eat : function(_type){ if(_type == '猫'){ console.log('猫粮') }else if (_type == "狗") { console.log('狗粮') }else{ console.log("吃饭"); } } }; obj.eat("狗");

    六.hasOwnProperty 查看该属性是否在这个对象本身上,只有在自身属性上才会返回真,在原型链上会返回假。

    function ClassA(){} ClassA.prototype.test = function(){ console.log('test') } var a = new ClassA(); a.test(); console.log(a.hasOwnProperty('test')); //false

    七:描述符(修饰符) 描述符是对一个属性的特性的描述,defineProperty设置描述符(修饰符),value设置属性值,configurable是否允许修饰符被改变 默认为false,enumerable 是否可以被枚举 默认为false,writable 是否可以被 = 等号改变 默认为false。

    var obj = { a : 1 }; var c = 666; Object.defineProperty(obj,'c',{ //value : 233, //enumerable : false, //writable : true,//他的值能否改变 //设置的时候调用 set : function(n){ //n 就是等号的右边的值 c = c*n; }, //获取的时候调用 get : function(){ return c; }, configurable : true,//是否可以再次修改修饰符 });
    Processed: 0.014, SQL: 9