JavaScript-this指向继承(构造函数和原型对象)
Posted 速速逃离月球表面
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript-this指向继承(构造函数和原型对象)相关的知识,希望对你有一定的参考价值。
文章目录
1. this关键字
- 构造函数中的this指的是新创建的对象,不代表这个类,指的是由类指针创建出来的对象
- 直接通过函数名调用函数(普通函数),this指的是全局对象window(构造函数只能通过new运算符调用,不能直接显示调用)
- 如果将函数作为对象的方法调用,this会指向该对象
- 普通函数中加不加this都可以,默认this指向window
1.1 案例:分析this指向
function foo() {
return this
}
var o = {
name: 'Jim',
func: foo
}
console.log(foo() === window) //对应第二种情况,输出结果:true
console.log(o.func() === o) //对应第三种情况,输出结果:true
1.2 更改this的指向
javascript 为专门提供了一些函数方法来处理函数内部 this 的指向问题,常用的有 bind()、call()、apply() 三种方法。
apply()方法和call()方法的区别:
function method(a, b) {
console.log(a + b)
}
method.apply({}, ['1', '2']) //数组方式传参,输出结果:12
method.call({}, '3', '4') //参数方式传参,输出结果:34
bind()方法:
function method(a, b) {
console.log(this.name + a + b)
}
var name = '张三'
var test = method.bind({ name: '李四' }, '3', '4') //-->表示method方法绑定了{name:'李四'}对象,method中的this指向的就是{name:'李四'}的对象
method('1', '2') //输出结果:张三12 -->该方法中的this指的是window
test() //输出结果:李四34
2. 错误处理
try-catch语法:
try{
可能会出现错误的代码
}catch(e ) { //e--->出现错误的代码的错误类型
错误出现后的处理代码
}
throw抛出错误对象案例演示:
try {
var e1 = new Error('错误信息') //创建错误对象
throw e1 //抛出错误对象,也可以与上一行合并为:throw new Error('错误信息')
} catch (e) {
console.log(e.message) //输出结果:错误信息
console.log(e1 === e) //判断e1和e是否为同一个对象,输出结果为:true
}
错误类型:
类型 | 说明 |
---|---|
Error | 普通错误,其余6种类型的错误对象都继承自该对象 |
EvalError | 调用eval()函数错误,已经弃用,为了向后兼容,低版本还可以使用 |
RangeError | 数值超出有效范围,如“new Array(-1)" |
ReferenceError | 引用了一个不存在的变量,如“var a = 1; a + b"(变量B未定义) |
SyntaxError | 解析过程语法错误,如" { ; } " “if()” “var a = new” |
TypeError | 变量或参数不是预期类型,如调用了不存在的函数或方法 |
URIError | 解析URI编码出错,调用encodeURI()、escape()等URI处理函数时出现 |
3. 继承
ES6之前并没有提供 extends 继承。可以通过构造函数+原型对象模拟实现继承,被称为组合继承
call():
作用:调用这个函数,并且修改函数运行时this指向将父类的this指向子类的this,实现子类继承父类的属性
实例对象:使用new运算符,调用构造函数创建的对象
3.1 借用构造函数继承父亲属性
原理: 通过call()方法 将父类的this指向子类的this,实现子类继承父类的属性
实例对象:使用new运算符,调用构造函数创建的对象
function Father(uname, age) { //Father构造函数是父类
//this指向父构造函数的对象实例
this.uname = uname
this.age = age
}
function Son(uname, age, score) { //Son构造函数是子类
//this指向子构造函数的对象实例
//将父构造函数的属性拿过来调用(实现父构造函数的借用),即实现对父构造函数的继承
Father.call(this, uname, age) //子类继承父类的属性
this.score = score //子类可以拥有自己的特有属性
}
var son = new Son('张三', 18, 100)
console.log(son) //输出结果:Son{uname:'张三',age:18,score:100}
ES6中继承父亲属性:
// 使用super继承(ES6)
class Father {
constructor(name, age) {
this.name = name
this.age = age
}
}
class Son extends Father {
constructor(name, age, score) {
super(name, age)
this.score = score
}
}
var son = new Son('张三', 20, 90)
console.log(son) //输出结果:Son {name: "张三", age: 20, score: 90}
3.2 利用原型对象继承父类方法
一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。
原型对象继承父类方法:将父类的实例对象作为子类的原型对象来使用
核心原理:
- 将子类所共享的方法提取出来,让子类的 prototype 原型对象 = new 父类()
- 本质:子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象
- 将子类的 constructor 从新指向子类的构造函数
function Father() { }
Father.prototype.money = function () {
console.log(100000)
}
function Son() { }
//Son.prototype = Father.prototype //这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
Son.prototype = new Father() //将父类的实例对象作为子类的原型对象
//这个是子构造函数专门的方法
//如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的原型对象
Son.prototype.constructor = Son //将原型对象的contructor属性指向子类
new Son().money() //调用父类的money()方法,输出结果:100000
Son.prototype.exam = function () { } //为子类增加exam()方法
console.log(Father.prototype.exam) //子类不影响父类,输出结果:undefined
原型链示意图:
class语法的本质:类和构造函数的使用非常相似,可以互相替代
<script>
class Person { }
console.log(Person.prototype) //类也有原型对象
Person.prototype.money = function () { //类也可以增加方法
console.log(100000)
}
new Person().money() //输出结果:100000
</script>
4. 类的本质
ES6之前通过 构造函数+原型 实现面向对象编程
ES6通过 类 实现面向对象编程
- class本质还是function,也可以简单认为类就是构造函数的另一种写法
构造函数的特征:
- 构造函数有原型对象prototype
- 构造函数原型对象prototype里面有constructor指向构造函数本身
- 构造函数可以通过原型对象添加方法
- 构造函数创建的实例对象由__proto__原型指向构造函数的原型对象
- 类的所有方法都定义在类的prototype属性上
- 类创建的实例,里面也有proto 指向类的prototype 原型对象
- 类可以通过原型对象来添加方法
- 所以ES6的类它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- 所以ES6的类其实就是语法糖.
- 语法糖:语法糖就是一种便捷写法. 简单理解, 有两种方法可以实现同样的功能, 但是一种写法更加清晰、方便,那么这个方法就是语法糖
补充:
URI和URL的区别:
- URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。
- URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
- 也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
http和https的区别:
https的SSL加密是在传输层实现的。
(1)http和https的基本概念
http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
https: 是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
https协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真实性。
(2)http和https的区别?
http传输的数据都是未加密的,也就是明文的,网景公司设置了SSL协议来对http协议传输的数据进行加密处理,简单来说https协议是由http和ssl协议构建的可进行加密传输和身份认证的网络协议,比http协议的安全性更高。
主要的区别如下:
Https协议需要ca证书,费用较高。
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
使用不同的链接方式,端口也不同,一般而言,http协议的端口为80,https的端口为443
http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
(3)https协议的工作原理
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
客户使用https url访问服务器,则要求web 服务器建立ssl链接。
web服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),返回或者说传输给客户端。
客户端和web服务器端开始协商SSL链接的安全等级,也就是加密等级。
客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话密钥,并传送给网站。
web服务器通过自己的私钥解密出会话密钥。
web服务器通过会话密钥加密与客户端之间的通信。
(4)https协议的优点
使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。
(5)https协议的缺点
https握手阶段比较费时,会使页面加载时间延长50%,增加10%~20%的耗电。
https缓存不如http高效,会增加数据开销。
SSL证书也需要钱,功能越强大的证书费用越高。
SSL证书需要绑定IP,不能再同一个ip上绑定多个域名,ipv4资源支持不了这种消耗。
以上是关于JavaScript-this指向继承(构造函数和原型对象)的主要内容,如果未能解决你的问题,请参考以下文章