一、原型对象相关方法

 ❏ in 关键字
❏ instanceof
❏ hasOwnProperty方法
❏ constructor构造器属性
❏ isProtoTypeOf方法

in关键字

作用 用来检查对象中是否存在某个属性(不区分实例属性和原型属性)

语法 “属性名” in 对象

<script>

    //01 提供一个构造函数
function Person(name) {
this.name = name;
} //02 设置构造函数的原型对象的属性
Person.prototype.sayHello = function () {
console.log("hello");
} //03 创建对象
var p1 = new Person(); //04 使用in关键字判断对象中是否存在以下属性:name age sayHello
console.log("age" in p1); //false
console.log("name" in p1); //true
console.log("sayHello" in p1); //true </script>

hasOwnProperty

作用 用来检查对象中是否存在指定的属性(只检查实例属性)

语法 对象.hasOwnProperty(“属性名”)

<script>

    //01 提供一个构造函数
function Person(name) {
this.name = name;
} //02 设置构造函数的原型对象的属性
Person.prototype.sayHello = function () {
console.log("hello");
} Person.prototype.des = "默认的描述信息"; //03 创建对象
var p1 = new Person(); //04 使用hasOwnProperty方法判断该属性是否是对象的实例属性
console.log(p1.hasOwnProperty("age")); //false
console.log(p1.hasOwnProperty("name")); //true
console.log(p1.hasOwnProperty("sayHello")); //false
console.log(p1.hasOwnProperty("des")); //false </script>
如何判断某对象中存在且只存在某个原型属性?
function isProperty(obj, property) {
return !obj.hasOwnProperty(property) && (property in obj);
}

constructor构造器属性

  • 原型对象中的constructor属性指向对应的构造函数

  • 实例对象中的constructor指向对应的构造函数,其中这里的constructor就是从原型中获取的constructor是实例对象中的原型属性而非实例属性

    //01 提供一个构造函数
function Person(name) {
this.name = name;
} //02 设置构造函数的原型对象的属性
Person.prototype.sayHello = function () {
console.log("hello");
};
Person.prototype.des = "默认的描述信息"; //03 创建对象
var p1 = new Person();
function isProperty(obj, property) {
return !obj.hasOwnProperty(property) && (property in obj);
}
console.log(isProperty(p1, "constructor")); //true

isProtoTypeOf

作用 判断是否是某个实例对象的原型对象

语法 构造函数.protoType.isPrototypeOf(对象)

<script>

    function Person() {
}
function Dog() {
} Person.prototype.name = "嘿嘿";
var p1 = new Person(); console.log(Person.prototype.isPrototypeOf(p1)); //rue
console.log(Object.prototype.isPrototypeOf(p1)); //true
console.log(Dog.prototype.isPrototypeOf(p1)); //false </script>

instanceof

作用 用于检查对象是否是某个构造函数(类型)的实例

语法对象 instance 构造函数

<script>

    var arr = [1,2,3];
console.log(arr instanceof Array); //true
console.log(Array instanceof Object); //true
console.log(arr instanceof Object); //true //instanceOf在判断的时候,算上整条原型链
//arr 是Array 和Object 任何一个类的示例 </script>

所有的对象都是Object构造函数(类型)的实例

二、JavaScript面向对象编程(继承)

继承·概念

继承 即通过一定的方式实现让某个类型A获取另外一个类型B的属性或方法。其中类型A称之为子类型,类型B称之为父类型或超类型。

javaScript中的继承

Object是所有对象的父级 | 父类型 | 超类型 js中所有的对象都直接或间接的继承自Object。

继承主要有两种方式:接口继承和实现继承。在js中只支持实现继承,实现继承主要依赖原型链来完成

JavaScript中实现继承的几种方式

> ① 原型式继承
> ② 原型链继承
> ③ 经典继承(借用构造函数)
> ④ 组合继承

其他语言中继承通常通过类来实现,js中没有类的概念,js中的继承是某个对象继承另外一个对象,是基于对象的。

原型式继承

原型式继承的方式A

<script>

    //01 提供一个构造函数
function Person(name,age) {
this.name = name;
this.age = age;
} //02 设置原型对象的属性
Person.prototype.className = "逍遥派1班"; //03 使用构造函数来创建原型对象
var p1 = new Person("张三",10);
var p2 = new Person("李四",20); //04 打印p1和p2对象中的className属性
console.log(p1.className);
console.log(p2.className); //结论:对象p1和p2继承了构造函数原型对象中的属性className
//但是这并不是严格意义上的继承 </script>

原型式继承的方式B

<script>
//01 提供一个构造函数
function Person(name,age) {
this.name = name;
this.age = age;
} //02 设置原型对象的属性
Person.prototype = {
constructor:Person,
className:"逍遥派1班"
}; //03 使用构造函数来创建原型对象
var p1 = new Person("张三",10);
var p2 = new Person("李四",20); //04 打印p1和p2对象中的className属性
console.log(p1.className);
console.log(p2.className); //结论:对象p1和p2继承了构造函数原型对象中的属性className
//注意:使用原型替换的方式实现继承的时候,原有原型对象中的属性和方法会丢失 </script>

原型式继承的方式C

    //01 提供超类型|父类型构造函数
function SuperClass() {
this.name = 'SuperClass的名称';
this.showName = function () {
console.log(this.name);
}
} //02 设置父类型的原型属性和原型方法
SuperClass.prototype.info = 'SuperClass的信息';
SuperClass.prototype.showInfo = function () {
console.log(this.info);
}; //03 提供子类型
function SubClass() {} //04 设置继承(原型对象继承)
SubClass.prototype = SuperClass.prototype;
SubClass.prototype.constructor = SubClass; var sub = new SubClass();
console.log(sub.name); //undefined
console.log(sub.info); //SuperClass的信息
sub.showInfo(); //SuperClass的信息
sub.showName(); //sub.showName is not a function

上面的方法可以继承超类型中的原型属性和原型方法,但是无法继承实例属性和实例方法

原型链继承

实现思想 利用原型(链)让一个对象继承另一个对象的属性和方法

实现本质 重写原型对象

原型链结构说明

  ① 每个构造函数都有原型对象
② 每个对象都有自己的构造函数
③ 每个构造函数的原型都是一个对象
④ 那么这个构造函数的原型对象也有自己的构造函数
⑤ 那么这个构造函数的原型对象的构造函数也有自己的原型对象
以上形成一个链式的结构,称之为原型链

原型链中的属性搜索原则

当访问某个对象的成员的时候,采取的搜索策略是:
① 先在自身中查找,如果找到则直接使用
② 如果在自身中没有找到,则去当前创建当前对象的构造函数的原型对象中查找
(1)如果找到了则直接使用
(2)如果在该原型对象中没有找到,则继续查找原型对象的原型对象
[1] 如果找到则直接使用
[2] 如果在原型对象的原型对象中也没有找到,则继续向上搜索....
`→` 重复上面的过程,直到Object的原型对象,若还是没有,则返回undefined(属性)或报错(方法)。

基本写法·代码示例

    //01 提供超类型|父类型
function SuperClass() {
this.name = 'SuperClass的名称';
this.showName = function () {
console.log(this.name);
}
} //02 设置父类型的原型属性和原型方法
SuperClass.prototype.info = 'SuperClass的信息';
SuperClass.prototype.showInfo = function () {
console.log(this.info);
}; //03 提供子类型
function SubClass() {
} //04 设置继承(原型对象继承)
SubClass.prototype = new SuperClass();
SubClass.prototype.constructor = SubClass; var sub = new SubClass();
console.log(sub.name); //SuperClass的名称
console.log(sub.info); //SuperClass的信息
sub.showInfo(); //SuperClass的信息
sub.showName(); //SuperClass的名称

可以继承父类型中的原型属性|原型方法,以及实例属性和实例方法

原型链继承注意点

① 确定原型和实例的关系 instanceof + isPrototypeOf()

② 完成继承之后,不能使用字面量的方式来创建原型[因为会切断原型]

③ 注意重写原型对象的位置,必须先实现原型继承,然后再设置子对象的原型属性和原型方法

原型链继承存在的问题

① 在创建子类型的实例时,不能向父类型的构造函数中传递参数

② 父对象的实例属性会转换为子类型的原型属性,如果父类型的实例成员是引用类型则会存在共享问题

    //01 提供父对象的构造函数
function SuperType() {
//02 在构造函数中中设置实例属性,该属性为引用类型
this.family = ['哥哥','姐姐','爸爸','妈妈'];
}; //03 提供子对象的构造函数
function SubType() {}; //04 设置原型继承
SubType.prototype = new SuperType(); //05 创建父对象构造函数的实例对象,并对内部的实例化属性进行修改
var subDemo1 = new SubType();
var subDemo2 = new SubType(); alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 subDemo1.family.push('爷爷','奶奶');
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶

经典继承(借用构造函数

基本思想 在子类型构造函数的内部调用(需要借助call|apply方法)超类型|父类型构造函数

  //01 提供父类型(对象)的构造函数
function SuperType(name) {
//02 在构造函数中中设置实例属性,该属性为引用类型
this.family = ['哥哥','姐姐','爸爸','妈妈'];
//实例属性
this.name = name;
}; SuperType.prototype.info = '父类型的原型属性';
//03 提供子类型(对象)的构造函数
function SubType() {
//经典继承|借用构造函数|伪造对象继承
//SuperType.call(this); //构造参数传递参数
SuperType.call(this,'张老汉');
}; //04 创建父类型的实例对象,并对内部的实例化属性进行修改
var subDemo1 = new SubType();
var subDemo2 = new SubType(); alert(subDemo1.info); //undefined
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 subDemo1.family.push('爷爷','奶奶');
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 //测试构造函数传递参数
alert(subDemo1.name);

经典继承又称为借用构造函数 | 伪造继承,这种方式能够继承父类型的实例属性,但是`无法继承父类型的原型属性和原型方法`。

经典继承的优点

① 可以在调用call方法的时候向构造函数传递参数

② 解决实例对象共享问题,通过调用父对象的构造函数来实现每个子类型(对象)的实例对象均拥有一份父类型实例属性和方法的副本。

经典继承存在的问题

① 冒充继承的方法无法实现函数的重用

② 无法继承父对象的原型属性和原型方法

组合继承(伪经典继承)

基本思想

> ① `使用原型链实现对原型属性和方法的继承`
> ② `通过伪造(冒充)构造函数来实现对实例属性的继承`

代码示例

//01 提供父类型的构造函数
function SuperType(name) {
//在构造函数中中设置实例属性,该属性为引用类型
this.family = ['哥哥','姐姐','爸爸','妈妈']; //实例属性
this.name = name;
}; //原型方法
SuperType.prototype.showName = function () {
console.log(this.name);
} //02 提供子类型的构造函数
function SubType(name) {
//冒充|伪造 构造参数传递参数
SuperType.call(this,name);
}; SubType.prototype = SuperType.prototype;
//SubType.prototype = new SuperType(); //02 创建父类型的实例对象,并对内部的实例化属性进行修改
var subDemo1 = new SubType('张三');
var subDemo2 = new SubType('张四'); alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 subDemo1.family.push('爷爷','奶奶');
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈 //测试构造函数传递参数
subDemo1.showName(); //张三
subDemo2.showName(); //张四

三、基本包装类型

基本类型 字符串 + 数值 + null + undefined + 布尔值

为了便于操作基本类型,ECMAScript提供了三个特殊的引用类型:Boolean + Number + String

说明 上述类型和其他的引用类型类似,同时也具备与各自的基本类型相应的特殊行为,每当我们读取一个基本类型的值的时候,后台就会创建一个对应的基本包装类型对象,从而让我们能够调用一些方法来操作这些数据。

var str = '测试字符串';
console.log(str.length); //5
console.log(str.substring(2)); //字符串

思考 属性和方法本是对象的特征,字符串如何能够拥有length属性以及其他类似subString等方法,内部怎么实现的?

基本类型值并不是对象,因此从逻辑上讨论他们不应该有属性和方法。 内部的具体处理

(1)创建String类型的一个实例对象
(2)在实例对象上面读取指定的属性(length),调用指定的方法(subString)
(3)销毁该对象

Number

Number是与数字值相对应的引用类型。

创建Number类型的对象:var num = new Number(10);

String

String是字符串的对象包装类型。

创建字符串类型的对象:var str = new String('hello World');

Boolean

Boolean是与布尔值对象的引用类型。

可以通过调用Boolean构造函数传递参数来创建boolean类型的对象。var bool = new Boolean(true);

基本包装类型的代码示例

    //001 String
var str = '测试字符串';
console.log(str.length); //5
console.log(str.substring(2)); //字符串 //002 Number
var num = new Number(10);
console.log(num); //Number {[[PrimitiveValue]]: 10}
console.log(typeof num); //object
console.log(typeof 10); //number //003 Boolean
var bool = new Boolean(true);
console.log(bool); //Boolean {[[PrimitiveValue]]: true}
console.log(typeof bool); //object
console.log(typeof true); //boolean

基本包装类型的注意点

对象还是基本数据类型值?

对象:通过new 调用构造函数创建出来的是对象

基本数据类型值:直接通过字面量方式赋值|通过省略new关键字调用构造函数方式创建的是基本数据类型值。

    var str1 = new String('hello');
var str2 = 'hello';
var str3 = String('hello');
说明:以上代码中,str1是对象,而str2和str3是字符串(基本数据类型值)

相等问题

基本类型值判断相等 => 值相等

引用类型值判断相等 => 值相等且引用相等

对象是引用类型,因此在判断相等的时候有诸多的注意点和容易出错的地方。

    var str1 = '这是一个字符串';           //基本数据类型
var str2 = String('这是一个字符串'); //基本数据类型
console.log(str1 == str2); //true 相等 var str3 = new String('这是一个字符串'); //引用类型-对象
console.log(str1 == str3); //true //值相等
console.log(str2 == str3); //true //值相等 console.log(str1 === str3); //false //值相等,但是引用不相等
console.log(str2 === str3); //false //值相等,但是引用不相等 //判断下面的变量是否相等
var num1 = 10; //基本数据类型
var num2 = new Number(10); //对象
console.log(num1 == num2); //true
console.log(num1 === num2); //false var bool1 = true;
var bool2 = new Boolean(true);
console.log(bool1 == bool2); //true
console.log(bool1 === bool2); //false

前端开发系列014-基础篇之Javascript面向对象(三)的更多相关文章

  1. 前端开发【第4篇:JavaScript基础】

    JavaScript简述 上一篇文章已经聊过JavaScript的历史了这里不再复述了直接切入正题,JavaScript是一门解释型.动态类型.弱类型语言. 解释型语言和编译型语言就类似看一本书,编译 ...

  2. 前端开发【第3篇:JavaScript序】

    JavaScript历史 聊聊JavaScript的诞生 JavaScirpt鼻祖:Bremdan Eich(布兰登·艾奇),JavaScript的诞生于浏览器的鼻祖网景公司(Netscape),发布 ...

  3. 前端开发【第6篇:JavaScript客户端(浏览器)】

    Web浏览器中的JavaScript 客户端JavaScript时间线 1.Web浏览器创建Document对象,并且开始解析web页面,解析HTML元素和它门的文本内容后添加Element对象和Te ...

  4. 前端开发【第5篇:JavaScript进阶】

    语句 复合表达式和空语句 复合表达式意思是把多条表达式连接在一起形成一个表达式 { let a = 100; let b = 200; let c = a + b; } 注意这里不能再块级后面加分号, ...

  5. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)

    背景 ​ 最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构.代码 ...

  6. 前端开发:css基础知识之盒模型以及浮动布局。

    前端开发:css基础知识之盒模型以及浮动布局 前言 楼主的蛮多朋友最近都在学习html5,他们都会问到同一个问题 浮动是什么东西?  为什么这个浮动没有效果?  这个问题楼主已经回答了n遍.今天则是把 ...

  7. ESP8266开发之旅 基础篇① 走进ESP8266的世界

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  9. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  10. openlayers5-webpack 入门开发系列一初探篇(附源码下载)

    前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...

随机推荐

  1. jmeter实现幂等测试的一种方法(案例)

    最近在研究怎样对电商系统的业务进行幂等测试,利用jmeter对单独业务开展幂等测试可能简便.直接有效吧 场景描述:买家每一笔订单选中商品后,系统会生成一个"ShopCartIds" ...

  2. 关于composer报错The openssl extension is required for SSL/TLS protection but is not available问题

    今天使用composer的时候得到了这个错误: The openssl extension is required for SSL/TLS protection but is not availabl ...

  3. 亚马逊aws_access_key_id和aws_secret_access_key利用

    00X01 信息泄露 敏感信息泄露,例如环境变量.例如,为了配置AWS CLI,需要设置以下环境变量: $ export AWS_ACCESS_KEY_ID=AKISIOSFODNN7EXAMPLE ...

  4. js--弹出对话框、改变控件内容、验证输入邮箱的合法性

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. 代码随想录第十一天 | Leecode 150. 逆波兰表达式求值、239. 滑动窗口最大值、347. 前k个高频词

    Leecode 150. 逆波兰表达式求值 题目链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/description ...

  6. 【记录】gnuplot|gnuplot怎么把多个图画成一个?

    版本:gnuplot 5.2 patchlevel 2 解决了无数次了还是反复忘,气,遂记. 下列程序的功能: 读取文件夹下的所有dat文件,并把所有dat的结果画在一张图里并标好图例: set te ...

  7. K8s进阶之Deployment的更新&回滚

    更新概述 更新指的是对 Deployment 所管理应用的配置.镜像版本等进行修改并应用到集群中的过程.通过更新 Deployment,你能够实现应用功能的升级.修复漏洞.调整资源分配等操作. 更新触 ...

  8. P10856 【MX-X2-T5】「Cfz Round 4」Xor-Forces题解

    题意: 给定一个长度为 \(n=2^k\) 的数组 \(a\),下标从 \(0\) 开始,维护 \(m\) 次操作: 给定 \(x\),设数列 \(a'\) 满足 \(a'_i=a_{i\oplus ...

  9. vue3 基础-列表渲染

    本篇讲列表渲染, 主要是对 v-on 指令配合 v-if 和一些数组相关的方法来体验 vue 的模板渲染方法. 数组元素的渲染 <!DOCTYPE html> <html lang= ...

  10. 2025年Android面试题含答案

    今年过完年,毫无悬念,成了失业人员之一,于是各种准备面试.前后将近一个月时间,面试10几家公司,基本上80%的企业都拿到了offer.这里面基本上大部分都是小企业居多,少部分中厂,两三家大厂.我并没有 ...