JavaScript高阶学习笔记(对象——原型链)

121 阅读6分钟

1.数据,变量和内存

1.数据,变量和内存

  • 什么是数据?

存储在内存中表示特定信息的东西,本质是0101;

数据的特点:可传递,可运算,一切且数据

所有内存操作的目标:数据

  • 什么是内存?

内存条通电后产生的可存储数据的空间(临时的)

内存条的产生和死亡:内存条(电路板)->通电->产生内存空间->存储数据->处理数据->断电->内存空间和数据都消失

一块小内存存储的两个数据:地址值和内存存储的数据

  • 内存的分类:

栈->存储全局变量和局部变量

堆->存储对象

  • 什么是变量?

可变化的量,由变量名和变量值组成;

每个变量对应一个小内存,变量名对应内存中的地址值,可以通过变量名来找到内存,变量值对象内存中保存的数据;

  • 内存,数据,变量之间的关系?

内存是用来存储数据的空间; 变量名是内存的标识; 注意:变量之间的赋值是值传递,而创建对象时发生的是地址传递;

JS引擎如何管理内存:

(1.)内存的生命周期:

分配小内存空间,得到它的使用权;

存储数据,可以反复进行操作;

释放小内存空间;

(2.)释放内存:

局部变量:函数执行完后自动释放;

对象:成为垃圾对象(没有变量指向它)->由垃圾回收器自动回收

2.对象

对象是什么?

保存多种数据的容器;有利于管理多个数据

对象的组成?

属性:属性名(字符串)和属性值组成,一般自己写的时候不用把属性名写成字符串;

方法:一种特殊的属性(特指函数)

访问对象数据的方法?

(1.)用对象.属性名来访问

(2.)用对象['属性名']或者对象[变量名]来访问(用于特殊情况,比如属性名是关键字或者想用变量时)

3.函数

函数也是对象,只不过保存的数据是代码,函数不能添加自己的属性或者方法,只能设置this的属性或者方法给它的实例对象使用;

创建函数的方法有三种:a.声明式 function xxx(){} b.赋值式 var xxx=function(){} c.调用构造函数 var xxx=new function() 回调函数的定义:a.自己定义的 b.自己没有调用 c.函数最终执行了

常见的回调函数有:a.dom事件回调函数 b.定时器回调函数 c.ajax请求回调函数 d.生命周期回调函数 IIFE:即匿名函数自调用,(function(){})()这种形式.最外层加上括号是为了把这个函数看成一个整体,优点是隐藏实现,不污染全局环境;

这里需要注意:JS必须加;的地方有两个,一个是小括号开头的语句前面要加分号,第二是中方括号开头的语句前面加分号;IIFE是第一种

关于函数中的this:

任何函数本质上都是通过某个对象来调用来(new一个实例对象也算是调用了函数,创建对象时就调用了构造函数,这时的this是那个实例对象)

所有函数内部都有一个this,它的值是调用函数的当前对象

(在这里我的理解是,只能是实例对象来调用函数,缺了明确的对象调用外,都是window对象来调用的函数,如果在全局声明一个函数,那么就相当于与给window对象添加了一个方法属性;)

<body>
<!--
1. this是什么?
  - 任何函数本质上都是通过某个对象来调用的,没有直接指定就是window对象
  - 所有函数内部都有一个变量this
  - 它的值是调用函数的当前对象
2. 如何确定this的值?
  - test():window
  - p.test():p
  - new test():新创建的对象
  - p.call(obj):obj
-->

<script type="text/javascript">
  function Person(color) {
    console.log(this)
    this.color = color;
    this.getColor = function () {
      console.log(this)
      return this.color;
    };
    this.setColor = function (color) {
      console.log(this)
      this.color = color;
    };
  }

  Person("red"); //this是谁? window

  var p = new Person("yello"); //this是谁? p

  p.getColor(); //this是谁? p

  var obj = {};
  p.setColor.call(obj, "black"); //this是谁? obj

  var test = p.setColor;
  test(); //this是谁? window

  function fun1() {
    function fun2() {
      console.log(this);
    }

    fun2(); //this是谁? window
  }
  fun1();
</script>
</body>

4.原型链

image.png

每个函数都有prototype属性(保留的是地址值,显示原型),指向它的原型对象,默认是一个空的object空对象(但是一些特殊的,比如内部函数,会有设定好的object对象属性);

每个实例对象都有-proto-属性(地址值,隐式原型)指向他的原型对象;不能直接操作隐式原型(ES6之前),但能操作显示原型;

原型对象中有constructor指向实例对象的构造函数;

构造函数对象被创建时,自动添加prototype属性和原型的constructor属性,之后当创建函数的实例时,由prototype赋值给实例的-proto-属性; 原型链的别名是隐式原型链,可见这个链主要是靠对象的-proto-属性来传导的;

原型链是为了查找对象的属性

什么是原型:

原型:一个函数可以看成一个类,原型是所有类都是一个属性,原型的作用就是给这个类的一个对象都添加一个统一的方法。

什么是原型链:

每一个原型都有一个-proto-,它指向它的prototype原型对象;它的prototype原型对象又有一个-proto-,指向它的prototype原型对象,就这样层层向上直到最终找到顶级对象Object的prototype,这个查询路径就是原型链

- prototype:原型 | 显式原型

proto:原型链(链接点)|隐式原型

流程是:先在自身查找,找到返回|如果没有则沿着-proto-链找,找到后返回|如果还是没有,则返回undefined;

在原型链中,需要注意:所有函数都是Function的实例,包括它本身;object的原型对象不是对象类型,它的原型是空;

读取对象的属性时,会从该对象的原型链中寻找,如果是设置对象的属性值,不会查找原型链,而是直接添加此属性;

方法一般定义在原型上,属性一般通过构造函数定义在对象本身上;

关于Instanceof方法 A instanceof B 如果B函数的显示原型在A对象的原型链上,则返回True;把A看成实例对象走-proto-,B看成函数走prototype,B走一步,A随意走,如果能重合则返回true;

Object和Function的关系

结论:

- Function的__proto__指向自己的prototype:

Function.__proto__===Function.prototype
- Object原型的隐式原型为null:	
Object.prototype.__proto__==null
- Object的__proto__指向Function的prototype:
ObjectObject__proto__===Function.__proto__===Function.prototype

/* 
* 对应名称
* - prototype:原型 | 显式原型
* - __proto__:原型链(链接点) |  隐式原型

* 从属关系
  prototype -> 函数的一个属性:对象{}
  __proto__ -> 对象Object的一个属性:对象{}
  对象的__proto__保存着该对象的构造函数的prototype
*/

function Test(){}
console.log(Test.prototype);

const test = new Test()
console.log(test.__proto__);

console.log(Test.prototype===test.__proto__);//true

// 原型也是一个对象,也有__proto_-
console.log(Test.prototype.__proto__ === Object.prototype);//true
// 最顶层Object的原型的__proto__为null
console.log(Object.prototype.__proto__);//null



// Function和Object:既是函数也是对象
// Test是由Function构造出来的  const Test = new Function()
// 因此Test的__proto__指向Function的prototype 
console.log(Test.__proto__===Function.prototype);//true
// 同样的道理  Function也是一个函数,也是被构造函数Function构造出来的  因此Function也应该有自己的__proto__和prototype
console.log(Function.__proto__);
console.log(Function.prototype);
console.log(Function.__proto__===Function.prototype);//true   所有Function的__proto__指向Function的prototype

const obj = {}
// obj是由new Object()而来的,const obj = new Object()
// Object也是一个Function
console.log(typeof Object);//function
// 因此 Object也是由Function构造而来的,const Object = new Function()
// 所以Object的__proto__指向Function的prototype
console.log(Object.__proto__===Function.prototype);//true
// 又因为Function.__proto__===Function.prototype,所以Object.__proto__===Function.__proto__
console.log(Object.__proto__===Function.__proto__);//true

Function与函数

Function是JavaScript提供的一种引用类型,通过Function类型创建Function对象。
在JavaScript中,函数也是以对象的形式存在的,每个函数都是一个Function对象。

//字面量方式创建函数

var fun =function () {

    console.log(100)

};

//函数声明方式创建函数

function fn () {

    console.log(200)

};

/*     创建Funtion类型的对象

*       var 函数名 = new Function('参数',''函数体)*/

var f = new Function('a','console.log(a)');

f(2);//以函数方式调用