前言
在开发鸿蒙的时候,我们经常需要断点查看变量的值,当看到__proto__ 这个东西的时候是不是有点陌生。本次我们分享的就和它有关
基本概念
JS对象
1.JS对象是 动态的属性(指 其自有属性)包,可以自由添加、更改、删除上面的属性
2.JS对象分为 函数对象 和 普通对象,每个对象都有__proto__属性,只有函数对象才有prototype属性
3.Object、Function 都是JS内置的函数, 类似的还有Array、RegExp、Date、Boolean、Number、String等
4.proto__属性的值是一个对象,这个对象叫原型对象,它有两个属性,constructor和__proto。constructor 用于记录实例是由哪个构造函数创建
// 字面量 对象
const o1 = {};
// 通过new Object创建对象
const o2 = new Object();
// 通过new一个函数 创建对象
const o3 = new f1();
// 常规函数声明
function f1(){};
// 类型为函数的变量
const f2 = function(){};
// 通过new Function创建一个函数,并赋值给变量f3
const f3 = new Function('str','console.log(str)');
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof f1); //function
console.log(typeof f2); //function
console.log(typeof f3); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
console.log(typeof o3); //object
o1 o2 o3 为普通对象,f1 f2 f3 为函数对象
1.凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象
2.f1,f2归根结底都是通过 new Function()的方式创建的
3.Function、Object 也都是通过 new Function()创建的
引用类型的四个规则
1.具有对象特性,可自由扩展属性,对属性进行增删改查
const obj = {}
const arr = []
const fn = function() {}
// 可以自由添加属性
obj.a = 1
arr.a = 1
fn.a = 1
console.log(obj.a) // 1
console.log(arr.a) // 1
console.log(fn.a) // 1
2.有一个隐式原型 proto 属性,属性值是一个普通的对象
const obj = {};
const arr = [];
const fn = function() {}
console.log('obj.__proto__', obj.__proto__);
console.log('arr.__proto__', arr.__proto__);
console.log('fn.__proto__', fn.__proto__);
3.隐式原型 proto 的属性值指向它的构造函数的显式原型 prototype
const obj = {};
const arr = [];
const fn = function() {}
obj.__proto__ == Object.prototype // true
arr.__proto__ === Array.prototype // true
fn.__proto__ == Function.prototype // true
4.当你试图访问一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 proto(也就是它的构造函数的显式原型 prototype)中寻找
const obj = { a:1 }obj.toString
// ƒ toString() { [native code] }
// obj 对象并没有 toString 属性,之所以能获取到 toString 属性,是遵循了第四条规则,从它的构造函数 Object 的 prototype 里去获取
Object
1.在JavaScript中,Object构造函数 创建一个对象包装器。Object是通过Function创建出来的,它是一种特殊的Function
2.如果给定值是null或undefined,将会创建并返回一个空对象,否则,将返回一个与给定值对应类型的对象
3.当以非构造函数(没有使用new)的方式被调用时,Object函数将转换为对象。它可以将任何值转换为对象。这种方式通常被用于将基本数据类型(如数字、字符串和布尔值)转换为相应的对象
4.只要是一个普通对象object,就可以用 new Object() 来实例化(Object() 是一个内置的构造函数),也就是说,所有的对象字面量都是 Object() 的实例
5.Object 作为构造函数,Object.prototype 指向一个具体的 原型对象 ,该 原型对象 作为对象的实例,它的 proto 值为 null,因而 Object.prototype.proto = null 时也就走到了 原型的尽头
Function
1.JS 内置了 Function() 构造函数 ,Function是所有函数的构造函数,因而 所有函数 都算作是 Function 的 实例对象
2.JS中的所有引用类型都是通过Function创建出来的
3.无论是Object还是自定义的函数,甚至Function本身都是通过Function函数创建出来的
4.Function是JS中的创造神
function fun() {}
function Fun() {}
我们使用function关键字来定义函数,但是有的时候函数名看起来更像类名。一般函数名第一个字母大写的时候,我们是想把这个函数当成构造函数使用
constructor 构造函数
构造函数是用于创建和初始化一个对象的特殊方法,通常我们会使用new关键字来调用构造函数,创建新的对象实例
JS中没有类的概念,于是设计了构造函数来实现继承机制
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 生成实例
const p = new Person('zhangsan', 18);
上面代码通过 new Person 生成了实例p,在Person这个构造函数内赋值给this的name和age属性是每个实例独有的,无法共享公共属性和公共方法。于是又设计了原型对象来实现共享属性和方法的功能
实例化
对 构造函数 使用 new 关键字可以创建出不同的 实例(实例的本质就是一个对象)
prototype 原型
JS的每个函数都有一个 prototype 属性 指向一个对象,这个对象就叫原型对象,也叫显示原型。原型对象有个属性为constructor指向该构造函数
每个对象中有一个属性叫__proto__,它叫 隐式原型
构造函数的prototype指向原型对象,原型对象的constructor指向构造函数
function Person() {};
var p = new Person();
构造函数的prototype属性的值(Person.prototype),也可以说成通过调用构造函数创建出来的那个实例对象的原型对象(p.proto)
1.只要是函数就有 prototype 属性,即函数的原型属性(由于对象是由函数创建的,因此对象也有prototype属性)
2.函数的原型对象也是对象(因此,这个对象也有对应的prototype属性)
3.由构造函数创建出来的对象会默认链接到其构造函数的这个属性上(constructor)
4.构造函数的 prototype 属性的作用是:实现数据共享(继承)
原型链
// 构造函数
function Preson(name, age) {
this.name = name;
this.age = age;
}
// 所有实例共享的公共方法
Preson.prototype.say = function (word) {
console.log(`${this.name}说:${word}`);
}
const p1 = new Preson('张三'