JS基础之JS的闭包、构造函数和实例化对象、原型对象和原型

一、JS的闭包

1、定义

闭包是指有权访问另一个函数作用域中的变量的一个函数。简单的说,你可以认为闭包是一个特别的函数,他能够读取其他函数内部变量的函数。

2、作用

正常的函数,在执行完之后,函数里面声明的变量就会被垃圾回收处理掉。但是闭包可以让一个函数作用域中的变量,在执行完之后依旧没有被垃圾回收处理掉。

3、缺点

内存泄漏导致变量无法被释放

栗子:

		function fn2() {  
            const c = 3 ;
            return function () {  
                console.log(c);
            }
        }
        // 闭包:一个函数可以访问另一个函数的变量
        // 缺点:内存泄漏导致变量无法被释放

        const res = fn2() ;
        res() ; //打印结果 3

二、面向对象

编程思想分为面向过程和面向对象:

  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了,它注重问题的解决,代表语言有C语言。
  • 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。完成对真实世界的模拟,把一个对象的共同特点抽离出现,有了所谓的’属性’和’方法’ ,代表语言有JAVA。

而JS并不是一个真正的面向对象的语言,js在模拟面向对象。

三、构造函数和实例化对象

构造函数

在对象的创建过程中,我们发现Object就是构造函数;new关键字调用构造函数就会得到一个对象。

	var a=new Object('666');
    console.log(typeof a); //打印结果 object

所有实例化的对象都共享方法:

	var arr1 = new Array() ;
    var arr2 = new Array() ;
    console.log(arr1.forEach == arr2.forEach); // true

new做了什么

  • 给函数添加了返回值 返回了一个对象
  • 把this指向了这个对象
  • 创建了一个对象
  • 执行构造函数(为新对象增添属性)
		function fn() {  
            console.log(this);
            console.log(666);
        }


        var res = fn() ;   // this指向window
        console.log(res);  // 函数没有返回值 undefined


        var res2 = new fn() ;   // this指向了对象
        console.log(res2);   // 返回了这个对象

任何一个函数都有可能成为一个构造函数,只要有new就可以
为了区分普通函数和构造函数,js建议构造函数使用大驼峰命名

四、 原型对象和原型

JS 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。

		function Cat(name, color) {
            this.name = name;
            this.color = color;
            this.meow = function () {
                console.log('喵');
            };
        }
        var cat1 = new Cat('大胖', '白色');
        var cat2 = new Cat('二胖', '黑色');
        console.log(cat1.meow === cat2.meow); //false

上面代码中,Cat函数是一个构造函数,函数内部定义了name属性和color属性,所有实例对象(上例是cat1)都会生成这两个属性,即这两个属性会定义在实例对象上面。
通过构造函数为实例对象定义属性,虽然很方便,但是有一个缺点。同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。

prototype属性

原型:任何一个对象都有原型 __ proto __ , 也就是这个构造函数,它指向对应的构造函数的原型对象;
__ proto __ 可以用于查找一个对象是否有某个属性或方法;

		function Dog(type){
            this.type=type;
            this.say='wang';
        }
        Dog.prototype.name='阿牧';
        const dog=new Dog('德牧')
        console.log(dog.__proto__==Dog.prototype);//true

原型对象:任何一个函数都有原型对象 prototype ,它的作用是给所有的实例化对象提供共有的属性和方法
JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……(原型链的尽头就是null)
JS基础之JS的闭包、构造函数和实例化对象、原型对象和原型_第1张图片
JS基础之JS的闭包、构造函数和实例化对象、原型对象和原型_第2张图片

		// prototype 原型对象 --- 解决属性和方法共享的问题
 
        function person(type , age) {
            // this.species = '人'
            this.type = type 
            this.age = age 
            this.speak = function () {  
                console.log(this.age);
            }
            // this.say = function () {
            //     console.log('我是人');                
            // }
        }
        person.prototype.species = '人'
        person.prototype.say = function () {
            console.log('我是人');
        }
        var fangZong = new person('男人' , 38)
        var keZong = new person('男人' , 18)
        console.log(fangZong.say == keZong.say); // true
        console.log(fangZong.species == keZong.species); // true
 
        console.log(fangZong.constructor); //   f person
 
        var arr = new Array()
        console.log(arr.constructor); // f array

constructor属性

constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的,实际上是返回自身的实例对象。由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。
上面代码中,x是构造函数Constr的实例,可以从x.constructor间接调用构造函数。这使得在实例方法中,调用自身的构造函数成为可能。

		function Constr() {}
		var x = new Constr();
		var y = new x.constructor();
		y instanceof Constr // true

instanceof

instanceof运算符返回一个布尔值,用于判断一个对象是否是一个构造函数的实例化对象。
*注:instanceof运算符只能用于对象,不适用原始类型的值。
对于undefined和null,instanceOf运算符总是返回false。

	undefined instanceof Object // false
	null instanceof Object // false

五、js面向对象的发展过程

  1. 工厂模式 创建一个对象,给对象加工(添加属性和方法) , 返回这个对象
    缺点:创建出来的对象和函数没有关系 ,方法也不共享

  2. new (创建对象,把this指向了这个对象和返回对象都由new完成了)
    解决的关系问题 , 方法依然不共享

  3. prototype 原型对象:提供共享的属性和方法

js面向对象的模拟最终版

  • 自身拥有的属性和方法写在构造函数中
  • 共有的属性和方法写在构造函数的原型对象上
		function Fn(type) {  
            this.type = type ;
            this.age = age ;
            // this.say = function () {  
            //     console.log('汪');
            // }
        }

        Fn.prototype.species = '狗' ;
        Fn.prototype.say = function () {  
            console.log('汪');
        }

        var dog = new Fn('狗子') ;
        console.log(dog);
        var dog2 = new Fn('柯基') ;
        console.log(dog);

        dog.say()

        // 每一个实例化对象都共享say方法
        console.log(dog.say == dog2.say);   // true

        // console.log(dog.__proto__);  // 指向这个构造函数
        // console.log(dog.constructor);  // Fn

你可能感兴趣的:(JS笔记,javascript,前端,开发语言)