浅谈面向对象的javascript几个特性
javascript中的this
和new
javascript是一门很灵活的语言,尤其是function
。他即可以以面向过程的方式来用,比如:
function getName() {return '张三'
}
getName()
也可以以面向对象的方式来用,比如:
function User() {this.name = '张三'
}var user = new User()
javascript
是如何实现面向对象编程的呢?他提供了new
这个关健字,有了new
就可以把对象进行实例化,比如:
function User(name, age){this.name = namethis.age = age
}
var zs = new User('zs', 20)
var ls = new User('ls', 30)
new
出来的两个实例,会开辟两块新的内存区域,来保存这些数据,同时有指针指向对象User
。所以就有instanceof
这个运算符,这个运算符的意思就是:a是不是A的实例。比如上例:zs instanceof User
的返回值是true
。
即然是面向对象的编程语言,那this
也是不可或缺的。在javascript
中,this
永远指向的是他的调用者。要理解这句话,我们举几个例子:
例子1
function test(){this.name = 'zs'
}
test()
当执行完成之后,这个name
会直接挂载到window
下面,因为是这样执行的:winow.test()
。
例子2
var game = document.getElementById('game')
game.addEventListener('click', function () {setTimeout(function () {this.innerText = 'Clicked'}, 1000)
})
这个例子很简单,点击某个元素的时候,1秒后,让他里面的html改成Clicked,可是你发现这样不好使,就是因为this
指向的问题,因为这里面的this
也指向window
了,所以你执行window.innerText
会返回Clicked
。
例子3
function User(name) {this.name = namethis.getName = function () {console.log(this.name)}
}
var u = new User('zs')
u.getName()
这里面的this
的指向没有问题,因为按照之前的原则,调用者是u
,也就是User
的实例,所以在方法getName
中,this.name
相当于u.name
,所以打印出zs
。
prototype和__proto__
prototype
javascript
是面向对象的语言,这个上面已经提过了,其他面向对象语言有一个必备我就是继承,很显然在ES6之前,没有extends
这个关键字,那么,javascript
就是利用prototype
的原型链来实现继承。先记住这句话,我们一会会说到继承。prototype
其实只是对象的一个属性,在Chrome控制台下,可以直接看出来,但是这个属性很特殊,这个属性下可以挂载任何的对象、方法、属性,而且挂载的东西可以反映到实例下对象上。说的比较绕,我们看个例子:
function User(name) {this.name = name
}
User.prototype.getName = function () {console.log(this.name)
}
var u = new User('zs')
u.getName()
我们在User.prototype
上面挂载了getName
的方法,在下面实例化User
之后的u
,就可以访问这个方法。
看到这,你可以有个疑问,既然是给实例化对象用的,那下面这种方式岂不是更好、更直观?
function User(name) {this.name = namethis.getName = function () {console.log(this.name)}
}
var u = new User('zs')
u.getName()
如果我们和Java语言进行对应,User
相当是Class
,name
相当于属性,getName
相当于里面的方法,完美映射!可以这样有一个问题啊,就是太费内存了。因为每new
一个对象,都会占用一块内存区域,这样User
里面方法属性越多,那么每个实例化的对象都会对这些进行 深复制
,那么占用的内存空间就越大。那么javascript
是如何通过prototype
来解决内存占用的问题的呢?这就需要引用__proto__
。
__proto__
定义:__proto__
是存在于实例化后对象
的一个属性,并且指向原对象的prototype
属性。
比如上例中的u.__proto__ === User.prototype
返回的是true
。可以在Chrome
控制台下查看u.__proto__
。
你会发现,不对吧,User
对象下也有__proto__
啊。那是因为User
也是Function
的实例,不信你可以试一下User.__proto__ === Function.prototype
的返回值。其实我们这样定义函数:function test(){}
是一个语法糖的写法,全拼应该是这样:var test = new Function('alert(1)')
。
现在我们来解释为什么使用prototype
能节省内存。不知道你有没有注意到上面一句代码u.__proto__ === User.prototype
,我为什么要使用三等?因为三等号除了值、类型外,内存地址也必须是相等的,也就是说User
不管实例化多少对象,他们的prototype
只有一份,放在User
里。客户端的浏览器环境不像服务器,内存还是比较紧张的,所以javascript
通过这种方式,来解决内存占用问题。
继承
方式一:直接继承
先举个例子:
var Animal = function (name) {this.name = name
}
Animal.prototype.walk = function () {console.log('I can walk!')
}
Animal.prototype.getName = function () {console.log('My name is ' + this.name + '!')
}var Dog = function (name) {this.name = name
}
Dog.prototype = Animal.prototypevar d = new Dog('Tom')
d.getName()
d.walk()
我们建立一个父类Animal
对象,建立一个子类Dog
,我们想让Dog
也有walk方法和getName方法,通过上面对prototype
的了解,我们最先想到的是Dog.prototype = Animal.prototype
,这样子类和父类的prototype
相等,那子类就有父类所有方法喽,继承链条是这样的:d.__proto__ === Dog.prototype === Animal.prototype
。
这样很直观,但是也有一个比较严重的问题。我们在扩展Dog
的时候,同时父类也会有对应的方法,这很显然是一个很严重的问题。
方式二:实例化继承
为了解决上面的问题,我们需要引入一个空函数,这个空函数做为桥梁,把子类和父类之间的连接切断。实现如下:
var F = function () {}
F.prototype = Animal.prototype
Dog.prototype = new F()Dog.prototype.say = function () {console.log('Say')
}
- 为什么是
Dog.prototype = new F()
呢?因为这样即可以继承Animal的所有方法,他的原型链是这样的:
d.__proto__ --> Dog.prototype --> new F().__proto__
执行walk
方法,F已经有了,所以就不会再找Animal
了
- 新增加的方法又不影响父类,这句怎么讲?因实例化的对象没有
prototype
属性!所以不会影响
浅谈面向对象的javascript几个特性相关推荐
- html5交互效果,浅谈HTML5 CSS3的新交互特性
本文标题的这副图片,是用Phosotshop制作的.但是,在搜索引擎中你却无法搜索到它,搜索引擎还没有强大到能够识别图片里面的文字.并且由于图片的体积不算太小,可能网速慢的网友在浏览的时候不得不耐心的 ...
- html5中的css特性,浅谈HTML5 CSS3的新交互特性
本文标题的这副图片,是用phosotshop制作的.但是,在搜索引擎中你却无法搜索到它,搜索引擎还没有强大到能够识别图片里面的文字.并且由于图片的体积不算太小,可能网速慢的网友在浏览的时候不得不耐心的 ...
- 【c++开篇】浅谈面向对象与面向过程(举例说明)
浅谈面向对象与面向过程 前言:刚接触C++第一时间,都会经常听到这样一话:C语言面向过程,C++面向对象.在老师模拟面试时,问道你对面向对象与面向过程的认识时,我有点懵答的不是很完整,刚好C++开篇写 ...
- 『软件工程13』浅谈面向对象方法,统一建模语言UML
浅谈面向对象方法UML 一.UML的含义 二.UML的主要内容 1.UML的概念模型 2.UML概念模型图例 三.UML的基本构造块 1.UML中的事物 (1)UML中的四种事物 (2)UML中各种事 ...
- 【转】浅谈面向对象的坏处
转自:https://blog.csdn.net/fishmai/article/details/52079766 1.性能. 现时C++可以说是支持OOP范式中最为常用及高性能的语言.虽然如此,在C ...
- 【JavaScript】——浅谈js(JavaScript)
[前言] 学习javascript的知识,原来在浏览网页时炫酷的动态效果就是js在幕后操作,js在Web开发中扮演着重要的角色,被广泛应用到各个领域:地图搜索,,用户注册.验证,网上购物.Web聊天- ...
- 浅谈面向对象的编程思想:如何优雅地把大象装进冰箱?
许多人刚学编程时,想必都听到过这样的话:"*语言是面向对象的,而***语言是面向过程的".那时的新人还懵懵懂懂,就被大牛或者书上的大牛骗去学了一种听起来很厉害的语言,然而学了半 ...
- 浅谈面向对象与女娲造人
由于课程需要,学习Java和面向对象也已经好几个月了,今天来浅浅的谈论一下我对面向对象的理解. 什么是面向对象? 如果你百科或者wiki一下,倒是能翻出一大堆来.如果你嫌这些答案不够深沉,不够装逼,甚 ...
- 浅谈面向对象程序设计方法
目录 定义 基本思想 早期发展 背景 审视问题域的视角 抽象级别 封装体 可重用性 特征 对象唯一性 抽象性 继承性 多态性(多形性) 开发方法 Booch方法 Coad方法 OMT方法 UML(Un ...
最新文章
- php定义变量f= e怎么写,php变量怎么定义-PHP问题
- nginx 集群部署_如何备份和还原您的Kubernetes集群资源和持久卷?
- 普林斯顿大学计算机科学与技术专业硕士项目拒信
- 移动app部分机型无法唤起h5支付宝支付_用这段代码对App说:喂,醒醒!App,到你出场了!...
- 解决redis-cli连接时出现Could not connect to Redis at 127.0.0.1:6379: Connection refused
- php imagick手册,PHP中使用Imagick实现各种图片效果实例
- Java Swing Mysql学生选课系统
- 麦肯锡指出布局金融生态圈对中国国内银行意义重大
- 一个有很多QT免费应用例程的网站
- redis和couchbase的比较
- Atitit 防烫伤指南与规范 attilax总结
- MODIS数据下载流程之地理空间数据云
- 电脑自动开机+自动输入密码
- android浏览器有桌面模式么,手机浏览器添加到主屏幕(桌面)的图标设置以及WebApp模式...
- hexo next主题去掉码市的Coding Pages等待页
- Keras实例教程(1)
- 阿里云香港节点全面故障给我们的启示
- 中国中试工厂市场现状研究分析与发展前景预测报告
- 区块链智能资产的“硬链接”思考
- 纽约时报称刘强东卷入悉尼嫩模性侵案 京东回应:深表同情
热门文章
- 阿里云 centos mysql_在阿里云的CentOS环境中安装配置MySQL的教程
- 《关于我的那些面经》滴滴Java岗(附答案)
- C++:17---sizeof运算符
- (十)nodejs循序渐进-高性能游戏服务器框架pomelo之介绍和安装篇
- mysql数据库老是被锁怎么解决_Mysql数据库全局锁是如何引起的,如何解决?
- codeforces 617A-C语言解题报告
- 解决:springcloud eureka 注册的服务config-client 状态Status:UNKNOWN (1)
- 解决 VS Code 保存时候自动格式化
- Hadoop之Flume详解
- Centos7 下yum安装mysql