js进阶一(prototype、prototype指向、原型继承、构造继承、组合继承、为window赋值新属性)

本文主要是介绍js进阶一(prototype、prototype指向、原型继承、构造继承、组合继承、为window赋值新属性),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • prototype
      • prototype中方法互相访问
      • prototype中找寻属性、方法
      • 改变prototype指向
      • 内置对象添加prototype方法
      • window全局对象
      • 通过原型实现继承
      • 继承例子
      • 借用构造函数
      • 组合继承

prototype

原型?
实例对象中有__proto__这个属性,叫原型,也是一个对象,这个属性是给浏览器使用,不是标准的属性----->proto----->可以叫原型对象

构造函数中有prototype这个属性,叫原型,也是一个对象,这个属性是给程序员使用,是标准的属性------>prototype—>可以叫原型对象

实例对象的__proto__和构造函数中的prototype相等—>true
又因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
实例对象的__proto__指向了构造函数的原型对象prototype

通过原型来添加方法,解决数据共享,节省内存空间

我们来看一个例子

function Person(name, age) {this.name = name;this.age = age;}//通过原型来添加方法,解决数据共享,节省内存空间Person.prototype.eat = function () {console.log("吃凉菜");};var p1 = new Person("小明", 20);p1.__proto__.eat();p1.eat()Person.prototype.eat()console.log(p1.constructor == Person);console.log(p1.__proto__.constructor == Person);console.log(p1.__proto__ == Person.prototype);console.log(p1.__proto__.constructor == Person.prototype.constructor);

输出如下:

吃凉菜
吃凉菜
true
true
true
true

原型指向可以改变
实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象

实例对象中有__proto__原型
构造函数中有prototype原型
prototype是对象
所以,prototype这个对象中也有__proto__,那么指向了哪里
实例对象中的__proto__指向的是构造函数的prototype
所以,prototype这个对象中__proto__指向的应该是某个构造函数的原型prototype

function Person() {}
Person.prototype.eat=function () {console.log("吃东西");
};var per=new Person();
console.dir(per);
console.dir(Person);console.log(Person.prototype.__proto__);//per实例对象的__proto__------->Person.prototype的__proto__---->Object.prototype的__proto__是nullconsole.log(per.__proto__==Person.prototype);
console.log(per.__proto__.__proto__==Person.prototype.__proto__);
console.log(Person.prototype.__proto__==Object.prototype);
console.log(Object.prototype.__proto__);

输出如下:

Personƒ Person()
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
true
true
true
null

prototype中方法互相访问

 function Animal(name,age) {this.name=name;this.age=age;}//原型中添加方法Animal.prototype.eat=function () {console.log("动物吃东西");this.play();};Animal.prototype.play=function () {console.log("玩球");};var dog=new Animal("小苏",20);dog.eat();

输出如下:

动物吃东西
玩球

prototype中找寻属性、方法

实例对象使用的属性或者方法,先在实例中查找,找到了则直接使用,找不到则,去实例对象的__proto__指向的原型对象prototype中找,找到了则使用,找不到则报错

function Person(age,sex) {this.age=age;//年龄this.sex=sex;this.eat=function () {console.log("构造函数中的吃");};}Person.prototype.sex="女";Person.prototype.eat=function () {console.log("原型对象中的吃");};var per=new Person(20,"男");console.log(per.sex);//男per.eat();

输出如下:

男
构造函数中的吃

我们在看下面一个例子:

function Person(age,sex) {this.age=age;this.sex=sex;}Person.prototype.sex="女";var per=new Person(10,"男");console.log(per.sex);//因为JS是一门动态类型的语言,对象没有什么,只要点了,那么这个对象就有了这个东西,没有这个属性,只要对象.属性名字,对象就有这个属性了,但是,该属性没有赋值,所以,结果是:undefinedconsole.log(per.fdsfdsfsdfds);

输出如下:

男
undefined

改变prototype指向

原型指向可以改变
实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象
构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(proto)指向也会发生改变

原型的指向是可以改变的
实例对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链

function Person(age) {this.age = age;}Person.prototype.eat = function () {console.log("人正在吃东西");};//学生构造函数function Student(sex) {this.sex = sex;}//学生的原型中添加方法----先在原型中添加方法Student.prototype.sayHi = function () {console.log("您好哦");};//改变了Student原型对象的指向Student.prototype = new Person(10);var stu = new Student("男");stu.eat();//  stu.sayHi();console.info(stu.sex)console.info(stu.age)console.dir(stu)

输出如下:

人正在吃东西
男
10Studentsex: "男"__proto__: Personage: 10__proto__:eat: ƒ ()constructor: ƒ Person(age)__proto__: Object

内置对象添加prototype方法

 String.prototype.sayHi = function () {console.log(this + "哈哈,萨芬");};//字符串就有了打招呼的方法var str2 = "sadly";str2.sayHi();

window全局对象

<script>//通过自调用函数产生一个随机数对象,在自调用函数外面,调用该随机数对象方法产生随机数(function (window) {//产生随机数的构造函数function Random() {}//在原型对象中添加方法Random.prototype.getRandom = function (min, max) {return Math.floor(Math.random() * (max - min) + min);};//把Random对象暴露给顶级对象window--->外部可以直接使用这个对象window.Random = Random;})(window);//实例化随机数对象var rm = new Random();//调用方法产生随机数console.log(rm.getRandom(0, 5));//全局变量</script>

通过原型实现继承

function Person(name, age, sex) {this.name = name;this.sex = sex;this.age = age;}Person.prototype.eat = function () {console.log("人可以吃东西");};Person.prototype.sleep = function () {console.log("人在睡觉");};Person.prototype.play = function () {console.log("生活就是不一样的玩法而已");};function Student(score) {this.score = score;}//改变学生的原型的指向即可==========>学生和人已经发生关系Student.prototype = new Person("小明", 10, "男");Student.prototype.study = function () {console.log("学习很累很累的哦.");};//相同的代码太多,造成了代码的冗余(重复的代码)var stu = new Student(100);console.log(stu.name);console.log(stu.age);console.log(stu.sex);stu.eat();stu.play();stu.sleep();console.log("下面的是学生对象中自己有的");console.log(stu.score);stu.study();console.dir(stu)

输出结果如下:

小明
10
男
人可以吃东西
生活就是不一样的玩法而已
人在睡觉
下面的是学生对象中自己有的
100
学习很累很累的哦.

在这里插入图片描述

继承例子

//动物的构造韩素function Animal(name,weight) {this.name=name; this.weight=weight;}//动物的原型的方法Animal.prototype.eat=function () {console.log("天天吃东西,就是吃");};//狗的构造函数function Dog(color) {this.color=color;}Dog.prototype=new Animal("哮天犬","50kg");Dog.prototype.bitePerson=function () {console.log("哼~汪汪~咬死你");};//哈士奇function ErHa(sex) {this.sex=sex;} ErHa.prototype=new Dog("黑白色");ErHa.prototype.playHost=function () {console.log("哈哈~要坏衣服,要坏桌子,拆家..嘎嘎...好玩,开心不,惊喜不,意外不");};var erHa=new ErHa("雄性");console.log(erHa.name,erHa.weight,erHa.color);erHa.eat();erHa.bitePerson();erHa.playHost();console.info(erHa)

效果如下:

哮天犬 50kg 黑白色
天天吃东西,就是吃
哼~汪汪~咬死你
哈哈~要坏衣服,要坏桌子,拆家..嘎嘎...好玩,开心不,惊喜不,意外不

在这里插入图片描述

借用构造函数

为了数据共享,改变原型指向,做到了继承—通过改变原型指向实现的继承
缺陷:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的了,所以,这就是问题
只能重新调用对象的属性进行重新赋值,

借用构造函数:构造函数名字.call(当前对象,属性,属性,属性…);
解决了属性继承,并且值不重复的问题
缺陷:父级类别中的方法不能继承

function Person(name, age, sex, weight) {this.name = name;this.age = age;this.sex = sex;this.weight = weight;}Person.prototype.sayHi = function () {console.log("您好");};function Student(name,age,sex,weight,score) {//借用构造函数Person.call(this,name,age,sex,weight);this.score = score;}var stu1 = new Student("小明",10,"男","10kg","100");console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);var stu2 = new Student("小红",20,"女","20kg","120");console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);

输出如下:

小明 10 男 10kg 100
小红 20 女 20kg 120

组合继承

function Person(name, age, sex) {this.name = name;this.age = age;this.sex = sex;}Person.prototype.sayHi = function () {console.log("阿涅哈斯诶呦");};function Student(name, age, sex, score) {//借用构造函数:属性值重复的问题十神Person.call(this, name, age, sex);this.score = score;}//改变原型指向----继承Student.prototype = new Person();//不传值Student.prototype.eat = function () {console.log("吃东西");};var stu = new Student("小黑", 20, "男", "100分");console.log(stu.name, stu.age, stu.sex, stu.score);stu.sayHi();stu.eat();console.dir(stu)

输出结果如下:

小黑 20 男 100分
阿涅哈斯诶呦
吃东西

在这里插入图片描述

这篇关于js进阶一(prototype、prototype指向、原型继承、构造继承、组合继承、为window赋值新属性)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125128

相关文章

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

Python如何调用另一个类的方法和属性

《Python如何调用另一个类的方法和属性》在Python面向对象编程中,类与类之间的交互是非常常见的场景,本文将详细介绍在Python中一个类如何调用另一个类的方法和属性,大家可以根据需要进行选择... 目录一、前言二、基本调用方式通过实例化调用通过类继承调用三、高级调用方式通过组合方式调用通过类方法/静

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

javaSE类和对象进阶用法举例详解

《javaSE类和对象进阶用法举例详解》JavaSE的面向对象编程是软件开发中的基石,它通过类和对象的概念,实现了代码的模块化、可复用性和灵活性,:本文主要介绍javaSE类和对象进阶用法的相关资... 目录前言一、封装1.访问限定符2.包2.1包的概念2.2导入包2.3自定义包2.4常见的包二、stati

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六