前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[JavaScript进阶]从JavaScript原型到面向对象

[JavaScript进阶]从JavaScript原型到面向对象

作者头像
用户1462769
发布2019-08-12 19:50:54
5320
发布2019-08-12 19:50:54
举报
文章被收录于专栏:全栈者全栈者

微信公众号:全栈者 作者:TinRongGao 欢迎关注我,一起学习,一起进步!

JavaScript支持面向对象吗?

本文来由:今天下午,笔者和一个做后端的同学一起聊天,聊到了JavaScript语言本身的相关内容,不可否认JavaScript本身确实有很多不可回避的问题,同学还指出说JavaScript连面向对象的没有,我告诉他虽然JavaScript在面向对象实现上因为和其他大多数后端语言不一样,但是它确实是支持面向对象的,故写此篇记录一下,分享给有需要的同学。

首先给出结论,JavaScript 的本身是支持面向对象的,它本身具备着强大灵活的 OOP 语言能力。但是对于使用过基于类的语言 (如 Java 或 C++) 的开发人员来说,JavaScript 确实有点令人困惑,因为它是动态的,并且本身不提供一个 class 实现。虽然在 ES6 中引入了 class 关键字,但它只是一个语法糖,本质还是基于JavaScript 的原型来实现的。

JavaScript的原型

说起JavaScript的面向对象,就必须要聊Javascript的原型。

我们知道JavaScript 语言本身只有一种数据结构,就是对象(Object),万物皆生于与对象,像我们常使用的函数,正则等均是对象(Object)衍生出来的实例对象。

代码语言:javascript
复制
Function instanceof Object //true
RegExp instanceof Object  //true
Number instanceof Object //true
Date instanceof Object //true

在每个实例对象中,都有一个私有属性( proto__ 属性),这个私有属性指向它的构造函数的原型对象(构造函数的prototype属性指向的对象 ),该原型对象也会有一个自己的私有属性( __proto ) ,然后它指向的构造函数的prototype属性指向的对象,然后这样一层层的向上直到一个对象的原型对象为 null,即代表JavaScript的原型到了顶层。出现了一个非常有趣的现象,从无到有对象,然后从对象再到万物。

看一下我之前画的一个图:

代码语言:javascript
复制
// 构造函数Person
小结一下
  1. Object,Function自定义函数类(Person)有prototype属性,其余没有
  2. Function的peototype属性与proto__属性指向同一内容(Function.__proto===Function.prototype)
  3. 由构造函数生成的对象与直接定义的对象原型链有差异(me.proto__._proto_===obj.__proto)
  4. 对象的constructor属性即它proto__属性被prototype指向的值(me.constructor===Person,me.__proto.constructor===Person)
  5. 任何对象由原型链查找到顶端为null(Object.prototype.proto===null)
代码语言:javascript
复制
function Person(name){
  this.name = name
}

Person.prototype.sayName = function(){
  console.log(this===me)       //true 
  console.log(this.__proto__===Person.prototype)       //true 
  return this.name
}

var me = new Person('FantasyGao')

var obj = {}

me.sayName()


console.log(me.constructor===Person)                                     //true  实例对象指向Person
console.log(me.__proto__.constructor===Person)                           //true  实例对象的__proto__指向Object
console.log(obj.constructor===Object)                                    //true  定义对象指向Object
console.log(obj.__proto__.constructor===Object)                          //true  定义对象的__proto__指向Object
console.log(Person.constructor===Function)                               //true  构造函数对象指向Function
console.log(Person.__proto__.__proto__.constructor===Object)                     //true  构造函数对象的__proto__.__proto__指向Object
console.log(Person.__proto__.constructor===Function)                            //true Object.prototype的__proto__即null
console.log(Function.constructor===Function)                             //true  Function函数对象指向Function
console.log(Function.__proto__.constructor===Function)                   //true  Function函数对象的__proto__指Function
console.log(Object.constructor===Function)                               //true  Object指向Function
console.log(Object.__proto__.constructor===Function)                     //true  Object的__proto__指向Function

console.log(me.__proto__===Person.prototype)                              //true 实例对象的__proto__即构造函数的prototype
console.log(obj.__proto__===Object.prototype)                             //true 定义对象的__proto__即Object的prototype
console.log(Person.__proto__===Function.prototype)                        //true 构造函数对象的__proto__即Function的prototype
console.log(Object.__proto__===Function.prototype)                        //true Object的__proto__即Function的prototype
console.log(Function.__proto__===Function.prototype)                      //true Function的__proto__即Function的prototype
console.log(Function.prototype.__proto__===Object.prototype)              //true Function.prototype的__proto__即Object的prototype

console.log(me.__proto__.__proto__===Person.__proto__.__proto__)          //true 实例对象的__proto__的__proto__的__proto__即null
console.log(me.__proto__.__proto__===obj.__proto__)                       //true 实例对象的__proto__的__proto__的__proto__即null

console.log(Function.prototype.__proto__.__proto__===null)                //true Function.prototype的__proto__的__proto__即null
console.log(Person.__proto__.__proto__.__proto__===null)                  //true Object.prototype的__proto__即null
console.log(Object.prototype.__proto__===null)                            //true Object.prototype的__proto__即null
console.log(me.__proto__.__proto__.__proto__===null)                      //true 实例对象的__proto__的__proto__的__proto__即null
console.log(obj.__proto__.__proto__===null)                               //true 定义对象的__proto__的__proto__即null


console.log(me.prototype)      //undefined
console.log(obj.prototype)      //undefined
console.log(Person.__proto__.prototype)    //undefined
console.log(me.__proto__.prototype)  //undefined
console.log(me.__proto__.__proto__.prototype)  //undefined   

JavaScript面向对象实现

1、函数封装实现
代码语言:javascript
复制
function Person(name,age) {
 let obj = {
  name:name,
  age:age
  }
  return obj
}

var me = Person('FantasyGao', 22)
var you = Person('Demi', 21)

console.log(me.name)
2、构造函数实现(new 操作符)
代码语言:javascript
复制
// new 构造函数生成对象
function Person(name,age) {
  this.name = name
  this.age = age
}

var me = new Person('FantasyGao', 22)

console.log(me.name)
3、prototype承载属性/方法
代码语言:javascript
复制
// prototype承载属性/方法
function Person(name,age) {
 this.name = name
  this.age = age
}

Person.prototype.country = 'China'
Person.prototype.say = function(){
  return 'i am Chinese'
}

var me = new Person('FantasyGao', 22)
var you = new Person('Demi', 21)

console.log(me.name)   //FantasyGao
console.log(me.say())  //China
console.log(you.say())  //China

console.log(me === you)  //false 
console.log(me.say === you.say)  //true(地址相同)
4、继承其他构造函数属性方法
代码语言:javascript
复制
// 继承其他构造函数属性方法

function Status(identity) {
  this.identity = identity
}

function Person(name,age) {
  this.name = name
    this.age = age
}

var me = new Person('FantasyGao', 22)

Status.call(me,'developer')
//Status.apply(me,['developer'])
//Status.bind(me)('developer')

console.log(me.identity)   // developer
5、继承其他构造函数属性方法结合prototype
代码语言:javascript
复制
// 继承其他构造函数属性方法结合prototype

function Status(identity) {
  this.identity = identity
}

function Person(name,age) {
  this.name = name
    this.age = age
}

Person.prototype = new Status('developer')  //利用prototype给Person绑定继承属性

var me = new Person('FantasyGao', 22)


console.log(me.identity)   // developer  原型链查找identity


// 原型链指示器错误修正
console.log(Person.prototype.constructor)  // Status

Person.prototype.constructor = Person

console.log(Person.prototype.constructor)  // Person
6、拷贝继承
代码语言:javascript
复制
// 拷贝继承
function deepCopy(obj,newObj={}){
  for(var k in obj){
    newObj[k]=obj[k]
    if(typeof(obj[k])==='object'){
      newObj[k]=(obj[k].constructor===Array)?[]:{}
      deepCopy(obj[k],newObj[k])
    }else {
      newObj[k]=obj[k]
    }
  }
  return newObj
}
var myObj={
  name:'FantasyGao',
  details:{
    sex:'男',
    data:[
     2,
     4,
     6
    ]
  },
  func:function() {
    this.status = 'func’s status'
  }
}

var myO= deepCopy(myObj)
var my1= deepCopy(myObj)

console.log(myO==my1)   //false

7、ES6中的class继承

代码语言:javascript
复制
class Person {
  constructor(name, sex) {
    this.name = name;
    this.sex = sex;
  }
  print() {
    return `my name is ${this.name}`;
  }
}
class Someone extends Person {
  constructor(name, sex, girlFriend) {
    super(name, sex);
    this.girlFriend = girlFriend
  }
  print() {
    console.log(super.print());
    console.log(`${this.name} have a ${this.girlFriend}`);
  }
}
const me = new Someone('FantasyGao', '男', 'Demi');
me.print() //my name is FantasyGao "FantasyGao have a Demi"

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

如上内容均为自己总结,难免会有错误或者认识偏差,如有问题,希望大家留言指正,以免误人,若有什么问题请留言,会尽力回答之。如果对你有帮助不要忘了分享给你的朋友或者点击右下方的“在看”哦!也可以关注作者,查看历史文章并且关注最新动态,助你早日成为一名全栈工程师!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JavaScript支持面向对象吗?
  • JavaScript的原型
    • 小结一下
    • JavaScript面向对象实现
      • 1、函数封装实现
        • 2、构造函数实现(new 操作符)
          • 3、prototype承载属性/方法
            • 4、继承其他构造函数属性方法
              • 5、继承其他构造函数属性方法结合prototype
                • 6、拷贝继承
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档