构造函数,原型与原型链的了解

376 阅读4分钟

一、构造函数

单例:单例模式就是一个函数。

高级单例:就是一个函数返回了一个对象;比普通高级在于有自己的私有变量

高级单例:
 var login = ! function () {
    var count = 100;
    var userName = 'dgdg'function init() {};

    function login() {}
    return {
      init,
      login,
      userName
    }
  }()

工厂模式(用的地方少):就是一个普通函数批量生成一些单例

工厂模式:可以批量生成一些单例
  function person(name, age, sex) {

    return {
      name,
      age,
      sex
    }
  }
  var per1 = person('账单', 13, 1)
  var per2 = person('haha',15,11)
  
  ......

构造函数:

// 构造函数模式
function Person(name, age) {
  var obj = {};
  obj.name = name;
  obj.age = age;
  obj.sayHello = function () {
    console.log("My name is" + this.name, "I am " + this.age + " years old");
  }
  return obj;
}
// 多了一个new
var p1 = new Person("chengxiaohui", 18);
p1.sayHello();

构造函数和工厂函数的区别:

  • 1.执行的时候
    • 普通函数执行person函数
    • 构造函数模式是通过new执行,哪Person就是一个类
    • 函数执行的返回值(p1)就是Person这个类的一个实列
  • 2.在函数代码执行的时候
    • 相同点:
      • 都是形成一个私有作用域,然后形参赋值->预解析(变量提升)->代码从上向下执行
    • 不同点:
      • 在代码执行之前,不用自己手动创建对象,浏览器会默认创建一个对象数据类型的值(这个对象其实就是当前类的一个实例)

      • this代表的就是当前的实例,然后把属性名和属性值赋值给当前的实例

      • 最后浏览器会默认把创建的这个对象返回

// 创建一个数组
var ary=[ ];//字面量方式创建
var ary2=new Array();//构造函数创建
// 无论通过哪种方式去创建,ary和ary2都是Array这个类的实例
  • 1.js中所有的类都是函数数据类型,它通过new执行变成一个类,但本质上它也是一个普通函数。
  • 2.在构造函数模式中,类中(函数体)出现的this.xxx=xxx中的this是当前类的一个实例
  • 3.p1和p2都是Person这个类的实列,所以都拥有sayHello这个方法,但是不同实例之间的方法是不一样的,实例和实例之间是单独的个体,所有的私有属性不是同一个
    • console.log(p1.sayHllo===p2.sayHello);//false

// 构造函数模式
function Person(name, age) {
  //在构造函数里,浏览器会默认给你创建一个对象
  //var obj = {};
  obj.name = name;
  obj.age = age;
  obj.sayHello = function () {
    console.log("My name is" + this.name, "I am " + this.age + " years old");
  }
  //浏览器默认返回了
  //return obj;
}
// 多了一个new
var p1 = new Person("chengxiaohui", 18);
var p2 = new Person("zhanghuan", 19);
p1.sayHello();

构造函数执行的时候不传参数可以省略()

function Fn() {

}
//没有写调用的小括号,但是依然会执行这个函数
var f1 = new Fn;
//作为普通函数执行必须要加小括号
Fn();

this的问题:在类中出现的this.xxx = xxx中的this都是当前类的实例,而某一个属性值(方法),方法中的this需要看方法执行的时候,前面是否有点,才能找到this指向谁

function Fn(name, age) {
  // 这个this指的是f1
  this.name = name;
  this.age = age;
  this.sayHello = function () {
    //这里的this要看这个函数执行的时候才知道
    console.log(this)
  }
}
var f1 = new Fn("chengxiaohui", 18);
f1.sayHello();//this 指的是f1
var f2=f1.sayHello;
f2();//this指的是window

构造函数返回值的情况

  • 默认类中给返回了一个对象
  • 如果写了return,return的是基本数据类型的话,还是返回那个默认对象
  • 如果写了return,return的是引用数据类型,返回的就是runturn的那个东西

instanceof

检测某一个实列都是属于这个类(引申用途:检测数据类型) 语法:

console.log(f1 instanceof Fn);
console.log(f1 instanceof Object)

二、原型

构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立的-->实例识别 如何将一个私有属性提升为公有属性

function Fn(name) {
  this.name = name;
}
//放在原型上成了公有属性
Fn.prototype.sayHello=function(){
	console.log("I can say hello~");
}
var f1 = new Fn("chengxiaohui");
var f2 = new Fn("zhanghuan");

原型需要焊死在脑子的话

  • 1.每一个函数数据类型都有一个天生自带的prototype(原型),这个属性值是一个对象数据类型
  • 2.在prototype上浏览器天生给它加了一个constructor属性,属性值是当前函数(类)的本身
  • 每一个对象也天生自带了__proto__,属性值是当前实例所属类的原型

image.png Object是js中所有对象数据类信息的基类(最顶层的类)

  • f1 instanceof Object ->true 因为f1通过__proto__可以向上查找,不过有多少级,最终都会找到Object上

三、原型链查找机制

f1.hasOwnProperty("x")

  • 1、通过对象.属性名的方式获取到属性值的时候,首先在对象的私有属性上进行查找,如果私有属性上有,就是私有的这个
  • 2、如果私有属性没有,则通过__proto__找到所属类的原型(类的原型上定义的属性和方法都是当前实例的公有属性和方法)
  • 3、如果原型上也没有,则继续通过原型的__proto__继续向上查找,一直到Object.prototype为止 这就是原型链的查找机制