JavaScript 面向对象编程浅谈

JavaScript 面向对象编程浅谈CreatedbyYiy codingLasted 年 7 月 20 日 JavaScript 创建对象的几种方式 第一种 对象字面量的方式 varperson firstName Mark lastName Yun age 25 sayHello function alert Hello

JavaScript创建对象的几种方式?

第一种: 对象字面量的方式

var person = { firstName:"Mark", lastName:"Yun", age:25, sayHello:function(){ 
    alert("Hello!") } };

第二种: 用function来模拟无参的构造函数

function Person(){ 
   }; var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class person.name="Mark"; person.age="25"; person.sayHello = function(){ 
    alert(person.name+" Hello!"); }

第三种: 用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)

function People(name,age,hobby){ 
    this.name=name;//this作用域:当前对象 this.age=age; this.hobby=hobby; this.sayHello=function(){ 
    alert("Hello,我叫"+this.name); } } var yiyi =new People("Yiyi",25,"coding");//实例化、创建对象 yiyi.sayHello();//调用eat方法

以上两种构造函数模式,把属性封装在一个对象里面。可以进行如下操作实例话对象:

  var yiyi = new People("Yiyi","18","coding");   var shuzi = new People("Shuzi","18","eating");

这时yiyi和shuzi会自动含有一个constructor属性,指向它们的构造函数People,即yiyi.constructor == People

构造函数存在的问题:构造函数方法很好用,但是存在一个浪费内存的问题。
上例People中,对于每一个实例对象,sayHello()方法都是一模一样的,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。console.log(yiyi.sayHello == shuzi.sayHello); //false,故可判断内存地址不同
不能让sayHello()方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?回答是可以的,这就是下面提到的混合方式来创建(构造函数与原型混合)




第四种: 用工厂方式来创建(内置对象)

先扔个链接吧,有时间再总结工厂模式.

第五种: 用原型方式来创建(prototype)

function Dog(){ 
   } Dog.prototype.name="旺财"; Dog.prototype.eat=function(){ 
    alert(this.name+"是个吃货"); } var xiaobai = new Dog(); xiaobai.eat();

第六种: 用混合方式来创建(构造函数与原型混合)

Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。我们可以利用这一点,把那些不变的属性和方法,直接定义在prototype对象上,如下:

function People(name,age){ 
   //构造函数 this.name = name; this.age = age; } People.prototype.sayHello = function(){ 
   //原型模式 alert("Hello,我是"+this.name); } var yiyi =new People("Yiyi",25); var shuzi = new People("Shuzi",18); console.log(yiyi.sayHello == shuzi.sayHello);//true,故可判断内存地址相同,节约了内存!

为了配合prototype属性,Javascript定义了一些辅助方法,帮助我们使用它。

1⃣️ isPrototypeOf()

这个方法用来判断,某个proptotype对象和某个实例之间的关系。

console.log(People.prototype.isPrototypeOf(yiyi));//true
2⃣️ hasOwnProperty()

每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。

console.log(yiyi.hasOwnProperty("name"));//true,本地属性 console.log(yiyi.hasOwnProperty("sayHello"));//false,继承自prototype对象的属性
3⃣️ in运算符遍历对象所有的属性
for(var prop in yiyi) { console.log("yiyi["+prop+"]="+yiyi[prop]); } *result:* yiyi[name]=Yiyi yiyi[age]=25 yiyi[sayHello]=function (){ 
   //原型模式 alert("Hello,我是"+this.name); }

JavaScript如何实现继承?

第一种:构造继承

构造继承又称”构造函数绑定”,是最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:

function People(name,age){ 
    this.name = name; this.age = age; } function Women(danceStyle){ 
    this.danceStyle = danceStyle; People.apply(this, arguments);//将父对象(People)的构造函数绑定在子对象(Women)上,实例化子对象后可以访问父对象的属性,如下图怪异现象。 }

这里写图片描述

这里写图片描述

这里写图片描述

第二种:原型继承

将Women的prototype对象,指向一个People的实例,那么所有Women的实例,就能继承People了。

function People(name,age){ 
    this.name = name; this.age = age; } function Women(danceStyle){ 
    this.danceStyle = danceStyle; } Women.prototype = new People();//将Women的prototype对象指向一个People的实例,它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。 Women.prototype.constructor = Women;//任何一个prototype对象都有一个constructor属性,指向它的构造函数。 如果没有"Women.prototype = new People()"这一行,Women.prototype.constructor是指向Women的; 加了这一行以后,Women.prototype.constructor指向People。

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。因此,在运行”Women.prototype = new People();”这一行之后,shuzi.constructor也指向People!这显然会导致继承链的紊乱(shuzi明明是用构造函数Women生成的),因此我们必须手动纠正,将Women.prototype对象的constructor值改为Women。这就是第二行的意思。

*编程时务必要遵守: 如果替换了prototype对象, o.prototype = {};,那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。  o.prototype.constructor = o;

第三种:直接继承prototype

改写上述栗子:

function People(){ 
   } People.prototype.sayHello = function(){ 
   alert("Hello!")} function Women(danceStyle){ 
    this.danceStyle = danceStyle; } Women.prototype = People.prototype;//将Women的prototype对象指向People的prototype对象,这样就完成了继承。

第四种:实例继承

由于”直接继承prototype”存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。

var emptyObj = function(){};   emptyObj.prototype = People.prototype;   Women.prototype = new emptyObj();   Women.prototype.constructor = Women;
function extend(Child, Parent) { 
        var emptyObj = function(){ 
   };     emptyObj.prototype = Parent.prototype;     Child.prototype = new emptyObj();     Child.prototype.constructor = Child;     Child.uber = Parent.prototype;//为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、"上一层"。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。不写也能调用的吧?   }

第五种:拷贝继承

简单说,就是把父对象的所有属性和方法,拷贝进子对象,这样也能够实现继承。

//这个函数的作用,就是将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。 function extend2(Child, Parent) { 
        var p = Parent.prototype;     var c = Child.prototype;     for (var i in p) {       c[i] = p[i];       }     c.uber = p;   }

快捷键

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216820.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午10:59
下一篇 2026年3月18日 上午10:59


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号