556 面向对象,构造函数

面向对象

JS本身就是一门基于面向对象编程的语言

  • 对象:泛指,一切我们需要研究的东西都是对象
  • 类:把这么多东西按照特点进行分组分类(大类和小类)
  • 实例:某一个类别中具体的某个事物

反推:通过对某一个实例的研究,我们会发现一些实例私有的特征,以及当前类下每一个实例都具备的公共特征

/*
 * arr1、arr2都是Array数组类的实例
 *   数组中的每一项内容都是当前实例私有的属性方法
 *   像push、pop等这些方法,都是每一个实例共同具备的公共的属性和方法(Array.prototype)
 */
let arr1 = [10, 20, 30];
let arr2 = [40, 50];
arr1.push(100);
arr2.push(100);

面向对象要掌握的能力

  1. 掌握面向对象编程的本质(类和实例之间的操作和构建)
  2. 以后在学习前端开发的时候,培养自己按照面向对象编程思想去研究和学习的思维
  3. 以后在开发的时候(尤其是组件、插件封装),我们应该基于面向对象思想去实现(创建类,并且创建类的不同实例,这样既可以保证每个实例的独立,也可以让实例之间具备共同的属性方法)

JS本身是基于面向对象编程的,所以JS的底层就是基于类和实例处理的,而且V8引擎默认就给JS这门语言设计了很多内置的类

  • 数据类型的内置类
  • Number 每一个数字都是它的实例
  • String
  • Boolean
  • Null、Undefined
  • Symbol、Bigint (特殊:不能被new)
  • Object 每一个对象都是Object类的实例
    • Object
    • Array
    • RegExp
    • Date
    • ...
  • Function 每一个函数都是Function类的实例
  • DOM操作的内置类
    • 每一个元素标签都有一个自己所属的类 (例如:HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget -> Object)
    • HTMLCollection
    • NodeList
    • ...
  • ...

构造函数

构造函数执行 new Xxx()

构造函数执行就是创建自定义类和类所对应的实例

=> Func被称为类, f1被称为当前类的一个实例

1.像普通函数执行一样,把函数执行,并且私有上下文和形参赋值等都操作一遍

2.特殊的操作

-> 在形成私有上下文之后,首先默认会创建一个对象(实例对象)

-> 让当前上下文中的THIS指向创建的这个对象

-> 接下来代码执行过程中所有的 this.xxx=xxx 都是给实例对象设置私有的属性和方法

-> 代码执行完成后,看是否有返回值。没有返回值默认返回创建的实例对象。如果有返回值,看返回值的类型,如果返回的是基本类型值,那么最后返回的还是实例对象。如果返回的是引用类型值,以自己返回的值为主。

因为构造函数执行既有普通函数执行的一面,也有自己特殊的一面,所以在所属私有上下文中,只有this.xxx=xxx才和实例对象有直接关系,而上下文中的私有变量等和实例对象没有必然的联系

/* 普通函数执行
1.形成一个私有的上下文 EC(FUNC),并且进栈执行(AO:name/age/n)
2.作用域链<EC(FUNC),EC(G)> ,初始this: window, 初始ARGUMENTS,形参赋值,变量提升
3.代码执行 window.name/age = 'xxx'/20
4.是否出栈释放
*/

function Func(name, age) {
  var n = 10;
  this.name = name;
  this.age = age;
}

/* 构造函数执行 new Xxx() */
var f1 = new Func('xxx', 20);
console.log(f1);


/* 普通函数执行 */
var f = Func('xxx', 20);
console.log(f); // => undefined


// =======================================


function Func(name, age) {
  var n = 10;
  this.name = name;
  this.age = age;
  // 如果上下文中有返回值
  // 返回基本类型:最后返回的是实例对象
  // 返回引用类型:最后以自己返回的为主(不在是返回实例对象)
  return function anonymous() { };
}
var f1 = new Func('xxx', 20);
console.log(f1); // => anonymous 


// --------------------------


function Func() {
  this.name = 'xxx';
  this.age = 20;
}

//构造函数执行,在new的时候,类后面的小括号是没必要非要加的,不加也会当做构造函数执行,加或者不加的区别:
//  => 不加小括号就没办法传递实参
//  => 运算优先级的问题  new Func()【19】  new Fun【18】  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
var f1 = new Func;
console.log(f1);

Func(); // 普通函数执行
Func; // 这是函数本身,函数没有执行 


// --------------------------


function Func() {
  this.name = 'xxx';
  this.age = 20;
  this.say = function say() {
    console.log(`my name is ${this.name},i'm ${this.age} years old!`);
  };
}
var f1 = new Func;
var f2 = new Func;
console.log(f1 === f2); // false
console.log(f1.say === f2.say); // false
console.log(f1.name === f2.name); // true

// 检测当前实例是否率属于这个类
console.log(f1 instanceof Func); // true

// 检测某个对象是否具备这个属性【in】,再以及是否为私有属性【hasOwnProperty】
console.log('say' in f1); // true
console.log(f1.hasOwnProperty('say')); //  true 

原文地址:https://www.cnblogs.com/jianjie/p/13862913.html