浅谈面向对象的javascript几个特性

javascript中的thisnew

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相当是Classname相当于属性,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属性!所以不会影响

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Netty】ChannelHandler和ChannelPipeline

一、前言 前面学习了Netty的ByteBuf,接着学习ChannelHandler和ChannelPipeline。 二、ChannelHandler和ChannelPipeline 2.1 ChannelHandler 在ChannelPipeline中,ChannelHandler可以被链在一起处理用户逻辑。 1. Channel生命周期 Channel接口定义了一个…

TS流头部的调整字段

见 http://hi.baidu.com/xumingxsh/blog/item/7b178903f1fa98014afb512f.html http://hi.baidu.com/xumingxsh/blog/item/ba50dba320a10da3caefd02f.html

electron 入坑记

最近有个想法,想写个简单的应用程序.平时在 Mac上开发,最终有可能运行在 Windows 上.看了一下,Electron 比较简单,应该可以一试. 关于安装 我机器上是有 Node 环境的,按着官方教程 直接 npm install electron 结果运行到 npm install.js就不到了..下午上班有事,也没管他,结果一…

自动驾驶安全驾驶规则_自动驾驶知识科普 自动驾驶汽车的七大核心技术

自动驾驶技术的本质是用机器视角去模拟人类驾驶员的行为,其技术框架可以分为三个环节:感知层、决策层 和执行层,具体涉及传感器、计算平台、算法、高精度地图、OS、HMI等 多个技术模块。目前自动驾驶L3商业化技术已经成熟,L4级/L5…

orcal数据操作

1.将数据库ZHSY完全导出,用户名baseusernj密码baseusernj导出到D:\daochu.dmp中 exp baseusernj/baseusernjZHSY filed:\daochu.dmp fully exp baseuserhf/baseuserhfZJCPDB fileC:\105hf.dmp ownerbaseuserhf 2.导入那个数据库的用户就写那个,第一个是用户名&#…

H264实时编码及NALU,RTP传输(ZZ)

rfc3984 Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1. 按照RFC3984协议实现H264视频流媒体nalu单元 包起始 0x 00 00 00 01H.264 NAL格式及分析器http://hi.baidu.com/zsw%5Fdavy/b ... c409cc7cd92ace.htmlhttp://hi.b…

学习具体计划书

计划书10大行动&#xff1a;1. 学习的时候不玩手机学习的时候把手机放在抽屉里&#xff0c;静音2. 及时复习学完一个章节的知识及时复习觉得有做分享的价值就做分享录视频3. 不学习的时间要好好利用花时间做好吃的&#xff0c;把身体弄好多看看心理学的书&#xff0c;<接触青…

初识python

课程介绍: python语言:python语言是一种计算机程序设计语言,实现人机交互的语言 python的课程设计python基础 (python开发工程师)数据库和SQL开发 (数据分析工程师)网络爬虫 (网络爬虫工程师)高数和数据分析 (数据分析工程师)人工智能和机器学习 …

photoshop最全快捷键列表

一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取) 矩形、椭圆选框工具 【M】 移动工具 【V】 套索、多边形套索、磁性套索 【L】 魔棒工具 【W】 裁剪工具 【C】 切片工具、切片选择工具 【K】 喷枪工具 【J】 画笔工具、铅笔工具 【B】 像皮图章、图案图…

python实例化对象做实参_如何在Python中记住类实例化?

好的&#xff0c;这是真实的场景&#xff1a;我正在编写一个应用程序&#xff0c;我有一个类&#xff0c;它表示某种类型的文件&#xff08;在我的例子中&#xff0c;这是照片&#xff0c;但细节与问题无关&#xff09;。照片类的每个实例对于照片的文件名都应该是唯一的。 问题…

bupt summer training for 16 #3 ——构造

https://vjudge.net/contest/172464 后来补题发现这场做的可真他妈傻逼 A.签到傻逼题&#xff0c;自己分情况 1 #include <cstdio>2 #include <vector>3 #include <algorithm>4 5 using std::vector;6 using std::sort;7 8 typedef long long ll;9 10 int n…

Python02期(北京)课程笔记索引

day01 初始python关于使用notepad运行python程序注释和语句分类 day02 命名方式和关键字数据类型数据类型转换 day03 变量与数据类型运算和运算符进制转换 day04 循环结构 day05 函数概述 day06 nonlocal和global 关键字详解 day07 python核心,内建函数高阶函数字…

python常用快捷键、写代码事半功倍_Pycharm常用快捷键总结及配置方法

工欲善其事必先利其器&#xff0c;Python开发利器Pycharm常用快捷键以及配置如下&#xff0c;相信有了这些快捷键&#xff0c;你的开发会事半功倍 一 常用快捷键 编辑类&#xff1a; Ctrl D 复制选定的区域或行 Ctrl Y 删除选定的行 Ctrl Alt L 代码格式化 Ctrl Alt O 优…

PHP中的魔术常量

魔术常量 PHP 向它运行的任何脚本提供了大量的预定义常量。不过很多常量都是由不同的扩展库定义的&#xff0c;只有在加载了这些扩展库时才会出现&#xff0c;或者动态加载后&#xff0c;或者在编译时已经包括进去了。 有八个魔术常量它们的值随着它们在代码中的位置改变而改…

Java中的继承性特性

继承性是java中的第二特性之一。而继承性最为关键的地方为&#xff1a;代码重用性的问题&#xff0c;利用继承性可以从已有的类中继续派生出新的子类&#xff0c;也可以利用子类扩展出更多的操作功能。 继承性的实现代码为&#xff1a;class 子类 extends 父类{ } 有以下3点说…

10大html5前端框架

Bootstrap 首先说 Bootstrap&#xff0c;估计你也猜到会先说或者一定会有这个( 呵呵了 )&#xff0c;这是说明它的强大之处&#xff0c;拥有框架一壁江山的势气。自己刚入道的时候本着代码任何一个字母都得自己敲出来挡我者废的决心&#xff0c;来让自己成长。结果受到周围各 种…

多媒体技术复习汇总 收藏

多媒体技术复习汇总 收藏 1. 什么是媒体&#xff1a;媒体是信息表示和传输的载体。2. 媒体分类&#xff1a;感觉媒体&#xff0c;表示媒体&#xff0c;表现媒体&#xff0c;存储媒体&#xff0c;传输媒体3. 多媒体技术的定义和特点&#xff1a;多媒体技…

PHP中的语法特点小结

PHP中的语法特点小结 1.PHP的变量开头要加上$符号,见到$就知道这个是一个变量 2.PHP中的常量才是不用加$符号的 3.PHP中$可以用来嵌套使用,从而实现动态的变量名的层级调用 4.PHP程序<?php开头,结尾可以加上?>,也可以不加 5.PHP中的常量有着魔术常量(系统自带的) 6.PH…

滚动行为

new router({ scrollBehavior (to, from, savaPosition) { if(savePosition) { //历史记录的前进后退记住的之前滚动到的位置 return savePosition } else { return {x: 0, y: 0} } //history模式下 定位到某个元素失效的解决办法 if(to.hash) { return { selector: to.h…