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

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。