原型链的引入

//如果想要使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的操作也都是一样,

//那么,为了共享数据,节省内存空间,是可以把属性和方法通过原型的方式进行赋值

//实例对象的原型__proto__和构造函数的原型prototype指向是相同的

//实例对象中的__proto__原型指向的是构造函数中的原型prototype

//实例对象中__proto__是原型,浏览器使用的
    //构造函数中的prototype是原型,程序员使用的

//原型链:是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

    console.log(per.__proto__==Person.prototype);  true

//构造函数中的this就是实例对象
    //原型对象中方法中的this就是实例对象

↓三处的打印是相同的

<script>function Person(age) {this.age=age;console.log(this);}Person.prototype.eat=function () {console.log(this);};var per=new Person(10);console.log(per);
</script>

__proto__指向分析

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

//per实例对象的__proto__------->Person.prototype的__proto__---->Object.prototype的__proto__是null

<script>function Person(age) {this.age=age;}var per=new Person(10);console.log(Person.prototype.__proto__==Object.prototype);//trueconsole.log(Object.prototype.__proto__); null
</script>

原型的指向改变,添加原型方法需要在原型改变之后

    function Person(age) {this.age = age;}指向改变了Person.prototype = {eat: function () {console.log("吃");}};先添加原型方法Person.prototype.sayHi = function () {console.log("您好");};var per = new Person(10);per.sayHi();</script>

实例对象和原型对象的属性分析

//因为JS是一门动态类型的语言,对象没有什么,只要点了,那么这个对象就有了这个东西,没有这个属性,只要对象.属性名字,对象就有这个属性了,但是,该属性没有赋值,所以,结果是:undefined
      console.log(per.fdsfdsfsdfds);  undefined

//实例对象访问这个属性,应该先从实例对象中找,找到了就直接用,找不到就去指向的原型对象中找,找到了就使用,找不到呢?=====
    //通过实例对象能否改变原型对象中的属性值?不能
    //就想改变原型对象中属性的值,怎么办?直接通过原型对象.属性=值;可以改变

    function Person(age,sex) {this.age=age;this.sex=sex;}Person.prototype.sex="女";var per=new Person(10,"男");console.log(per.sex);男

有趣的原型链

//原型链:实例对象和原型对象之间的关系,通过__proto__来联系

↓ 以下是普通的div标签的原型链指向

divObj.__proto__---->HTMLDivElement.prototype的__proto__

--->HTMLElement.prototype的__proto__---->Element.prototype的__proto__

---->Node.prototype的__proto__---->EventTarget.prototype的__proto__

---->Object.prototype没有__proto__,所以,Object.prototype中的__proto__是null

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>title</title><script>原型链:实例对象和原型对象之间的关系,通过__proto__来联系</script>
</head>
<body>
<div id="dv"></div>
<script>var divObj=document.getElementById("dv");console.dir(divObj);
</script>
</body>
</html>

继承

* 面向对象编程思想:根据需求,分析对象,找到对象有什么特征和行为,通过代码的方式来实现需求,要想实现这个需求,就要创建对象,要 想创建对象,就应该显示有构造函数,然后通过构造函数来创建对象.,通过对象调用属性和方法来实现相应的功能及需求,即可
    * 首先JS不是一门面向对象的语言,JS是一门基于对象的语言,那么为什么学习js还要学习面向对象,因为面向对象的思想适合于人的想法,编程起来会更加的方便,及后期的维护....
    * 面向对象的编程语言中有类(class)的概念(也是一种特殊的数据类型),但是JS不是面向对象的语言,所以,JS中没有类(class),但是JS可以模拟面向对象的思想编程,JS中会通过构造函数来模拟类的概念(class)

* 共同的特征和行为
    * 特征--->属性
    * 行为---方法
    *
    * 面向对象的特性:封装,继承,多态
    *
    * 封装:就是包装
    * 一个值存储在一个变量中--封装
    * 一坨重复代码放在一个函数中--封装
    * 一系列的属性放在一个对象中--封装
    * 一些功能类似的函数(方法)放在一个对象中--封装
    * 好多相类似的对象放在一个js文件中---封装
    *
    * 继承: 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承
    * 继承也是为了数据共享,js中的继承也是为了实现数据共享
    *
    * 原型作用之一:数据共享,节省内存空间
    * 原型作用之二:为了实现继承

* 多态:一个对象有不同的行为,或者是同一个行为针对不同的对象,产生不同的结果,要想有多态,就要先有继承,js中可以模拟多态,但是不会去使用,也不会模拟,

实现继承   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();

借用构造函数

//为了数据共享,改变原型指向,做到了继承---通过改变原型指向实现的继承

//缺陷:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的了,所以,这就是问题

//解决方案:继承的时候,不用改变原型的指向,直接调用父级的构造函数的方式来为属性赋值就可以了------借用构造函数:把要继承的父级的构造函数拿过来,使用一下就可以了

//借用构造函数:构造函数名字.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);小明 10 男 10kg 100

组合继承

//原型实现继承
//借用构造函数实现继承
//组合继承:原型继承+借用构造函数继承
        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);小黑 20 男 100分stu.sayHi();阿涅哈斯诶呦stu.eat();吃东西

拷贝继承

        var p={name:'wutong',age:12};var p1={};for(var key in p){p1[key]=p[key];}console.dir(p1);console.log(p==p1);//falsefunction Person() {}Person.prototype.name='zhangsan';Person.prototype.age=12;var p2=new Person();for(var key in Person.prototype){p2[key]=Person.prototype[key];}console.dir(p2)

继承总结

//继承,类与类之间的关系,面向对象的语言的继承是为了多态服务的,
    //js不是面向对象的语言,但是可以模拟面向对象.模拟继承.为了节省内存空间

//继承:
    /*
    * 原型作用: 数据共享 ,目的是:为了节省内存空间,
    * 原型作用: 继承  目的是:为了节省内存空间
    *
    * 原型继承:改变原型的指向
    * 借用构造函数继承:主要解决属性的问题
    * 组合继承:原型继承+借用构造函数继承
    * 既能解决属性问题,又能解决方法问题
    * 拷贝继承:就是把对象中需要共享的属性或者犯法,直接遍历的方式复制到另一个对象中

逆序继承看原型

*理解:通过原型实现了继承,所以子初始化的时候必须调用改变的原型指向的初始化。

*f3  age=30  → f3.__proto__.age=20 (f1)  →  f1.__proto__.age=10;

        function F1(age) {this.age = age;}function F2(age) {this.age = age;}F2.prototype = new F1(10);function F3(age) {this.age = age;}F3.prototype = new F2(20);var f3 = new F3(30);console.log(f3.age);  30

函数的声明和函数表达式

    函数的声明function f1() {console.log("我是函数");}f1();函数表达式var ff=function () {console.log("我也是一个函数");};ff();

函数声明和函数表达式的区别

//函数声明如果放在if-else的语句中,在IE8的浏览器中会出现问题,函数声明在if-else块中,块外无法实现调用
    //以后宁愿用函数表达式,都不用函数声明

           if(true){function f1() {console.log("哈哈,我又变帅了");}}else{function f1() {console.log("小苏好猥琐");}}f1();var ff;if(true){ff=function () {console.log("哈哈,我又变帅了");};}else{ff=function () {console.log("小苏好猥琐");};}ff();

函数中的this的指向
     * 普通函数中的this是谁?-----window
     * 对象.方法中的this是谁?----当前的实例对象
     * 定时器方法中的this是谁?----window
     * 构造函数中的this是谁?-----实例对象
     * 原型对象方法中的this是谁?---实例对象

    <script>"use strict";//严格模式function f1() {console.log(this);undefined}f1();function f1() {console.log(this); window}f1();var timeId=setInterval(function () {console.log(this);  windowclearInterval(timeId);},1000);function Person() {console.log(this);Person{}this.sayHi=function () {console.log(this); Person{sayHi}};}Person.prototype.eat=function () {console.log(this); Person{sayHi}};var per=new Person();console.log(per); Person{sayHi}per.sayHi();per.eat();</script>

普通函数和构造函数

*语法上只有大小写的区分,使用上构造函数通过new来实现调用,普通函数直接调用即可

    普通函数function f1() {console.log("文能提笔控萝莉");}f1();构造函数---通过new 来调用,创建对象function F1() {console.log("我是构造函数,我骄傲");}var f=new F1();

区分函数和对象

//函数是对象,对象不一定是函数

//对象中有__proto__原型,是对象
    //函数中有prototype原型,是对象

//如果一个东西里面有prototype,又有__proto__,说明是函数,也是对象

    对象中有__proto__,函数中应该有prototypeconsole.dir(Math);  中有__proto__,但是没有prorotype

数组中函数的调用

*javascript是弱类型语言,所以数组中可以存放各种数据类型,但是为了方便遍历,尽量存放同种类型

    <script>var arr=[function () {console.log('hello world!')},function () {console.log('hello world!')}];arr.forEach(function (ele) {ele();})</script>

JavaScript学习记录十六相关推荐

  1. JavaScript学习(十六)—实现购物车加减数量,计算总金额

    JavaScript学习(十六)-实现购物车加减数量,计算总金额 代码如下: <table border="2" cellspacing="0" soli ...

  2. JavaScript学习总结(十六)——Javascript闭包(Closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什 ...

  3. Dubbo学习记录(十六)--服务调用【二】 - Invoker的调用、ProxyFactory、Protocol、Filter,Exchanger, Transporter扩展点

    服务调用的前置学习[二] 服务调用涉及到的东西比较多, 需要一个个的理解透彻, 最终才能串起来: 服务端DubboInvoker的包装 DubboInvoker的生成是在服务导出的过程中创建的:由于D ...

  4. 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用

    目录 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用 16.1 LVM的工作原理 16.1.1 LVM常用术语 16.1.2 LVM优点 16.2 创建LVM的基本步骤 16.2 ...

  5. java学习记录十五:集合二Collections、Set、Map

    java学习记录十五:集合二 一.Collections工具类 一.解释 二.常用方法 1.打乱集合顺序 2.按照默认规则排序 3.按指定规则排序 4.批量添加元素 二.可变参数 一.解释 二.写法 ...

  6. Java基础学习——第十六章 Java8新特性

    Java基础学习--第十六章 Java8 新特性 Java8(JDK8.0)较 JDK7.0 有很多变化或者说是优化,比如 interface 里可以有静态方法和默认方法,并且可以有方法体,这一点就颠 ...

  7. 花书+吴恩达深度学习(十六)序列模型之双向循环网络 BRNN 和深度循环网络 Deep RNN

    目录 0. 前言 1. 双向循环网络 BRNN(Bidirectional RNN) 2. 深度循环网络 Deep RNN 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花 ...

  8. JavaScript学习(十五)—内部样式与外部样式的修改与设置

    JavaScript学习(十五)-内部样式与外部样式的修改与设置 (一).行内样式 获取方式:元素节点.style.CSS属性名称: 注意:如果CSS属性中包含"-",那么需要采用 ...

  9. JavaScript学习(十四)—元素节点关系和特殊节点

    JavaScript学习(十四)-元素节点关系和特殊节点 一.元素节点 (1).parentElement: 获取某元素的父元素,它和parentNode的区别是parentElement获取到的值时 ...

  10. JavaScript学习(十二)—removeAttribute方法、hasAttribute方法、createAttribute方法以及setAttributeNode方法

    JavaScript学习(十二)-removeAttribute方法.hasAttribute方法.createAttribute方法以及setAttributeNode方法 (一).removeAt ...

最新文章

  1. 使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程(十五)
  2. activity的使用(八):生命周期
  3. hilb--生成Hilbert(希尔伯特)矩阵
  4. 【js与jquery】三级联动菜单的制作
  5. flower.php,flower.php
  6. python中str函数_python字符串str的常用函数
  7. 单个对象和多个对象在内存中的结构图
  8. ZooKeeper(四)ZooKeeper的简单使用
  9. 大数据开发笔记(三):Mapreduce
  10. access里面的表达式运用_Access表达式
  11. 黑马程序员————银行业务调度系统
  12. 利用kaptcha生成登录验证码
  13. 图形化开发(五)011-Three.js之Geometry几何体——立方体、圆形、圆锥
  14. c语言中最小公倍数算法,常见算法:C语言求最小公倍数和最大公约数三种算法...
  15. python基础教程: 利用turtle库绘制笑脸和哭脸的例子
  16. 大数据的一些基本概念
  17. Windows11重置提示找不到恢复环境怎么解决?
  18. Java 内部类简介,理解,特点,注意事项
  19. 2013新春奉送 Android摄像头开发完美demo--- 循环聚焦 缩放大小 旋转picture 查询支持的pict
  20. 操作系统实验报告 实验1 VMware虚拟机配置与linux基本命令(答案全)

热门文章

  1. 霸榜GitHub!程序员必懂的15大定律和7大原则
  2. doPost 乱码问题解决
  3. 终端进入服务器,mac使用Shell(终端)SSH连接远程服务器的方法
  4. 海康录制视频文件无法播放以及FFmpeg最新版下载
  5. js的柯里化(curry)
  6. 与卡耐基梅隆大学博士交流笔记
  7. 【颜纠日记】祛痘广告那么神?分享确切的祛痘方式。
  8. 国家职业资格:计算机网络管理员
  9. js 实现一个打点计时器
  10. cocos creator 加载微信云端图片