javaScript快速入门之构造函数与原型对象

this

  • 解析器在调用函数每次都会向函数内部传递一个隐含的参数
  • 这个隐含的参数就是this,this指向的是一个对象
  • 这个对象我们称为函数执行的上下文对象
  • 根据函数的调用方式不同,this指向不同的对象
function fun(a){
	console.log(a);
	console.log(this); // object window   obj
}
fun(3);


function fun(){
	console.log(this.name);
}
var obj = {
	name:'bob',
	say:fun
}

var obj2 = {
	name:'tom',
	say:fun
}

fun(); // 以函数的形式调用,this永远都是 window
obj.say(); // bob 以方法的形式进行调用时,this就是调用方法的那个对象 this -》 obj
obj2.say(); // tom


function fun(){
	console.log(obj.name);
}

var obj = {
	name:'bob',
	say:fun
}
var obj2 = {
	name:'tom',
	say:fun
}

obj.say(); // bob,但是如果在创建一个对象
obj2.say(); // bob 在这里面写死了,就不行


使用工厂方法创建对象

  • 通过该方法大批量创建对象
function box(){
	// 创建一个新对象
	var obj = new Object();
	// 向对象中添加属性
	obj.name = 'tom',
	obj.ahe = 13,
	obj.gender = 'man',
	obj.say = function(){
		alert(this.name);
	}
	// 将新的对象返回
	return obj;
}

var box1 = box(); 
var box2 = box(); // 虽然创建方便但是比较固定,每次返回的属性都是相同

// 传参会灵活
function box(name,age,gender,){
	// 创建一个新对象
	var obj = new Object();
	// 向对象中添加属性
	obj.name = name,
	obj.age = age,
	obj.gender = gender,
	obj.say = function(){
		alert(this.name);
	}
	// 将新的对象返回
	return obj;
}

构造函数

  • 使用工厂方法虽然可以节省代码冗余,但是使用构造的函数都是Object这个类型,导致我们无法准确的去区分类。

  • 构造函数:就是一个普通的函数,不同是构造函数习惯首字母大写

  • 普通函数与构造函数的区别

    • 普通函数直接调用,而构造函数需要使用new关键字来调用
  • 构造函数的执行过程

    • 1.立即创建一个新的对象
    • 2.将新建的对象设置为函数中的this
    • 3.逐行执行函数中的代码
    • 4.将新建的对象作为返回值返回
  • 使用同一个构造函数所创建的对象,我们称为一类对象,也将一个构造函数称为一个类

    • 将通过一个构造函数创建的对象,称为该类的实例
  • function Box(){
    	this.name = 'tom',  // this就代表新建box这个对象,name加入到新对象中
    	this.age = 18,
    	this.say = function(){
    		alert(this.name);
    	}
    }
    var box = Box();
    
    // 改造
    function Box(name,age){
    	this.name = name,  // this就代表新建box这个对象,name加入到新对象中
    	this.age = age,
    	this.say = function(){
    		alert(this.name);
    	}
    }
    var box1 = Box('bob',12);
    var box2 = Box('tom',13);   // 箱子类的实例
    
  • 使用instanceof检查一个对象是否是一个类的实例

    • console.log(box instanceof Box); // true
      console.log(box instanceof Object); // 所有对象都是Object的后代
      

构造函数的修改

  • 创建Box构造方法

    • 构造函数每执行一次就会创建一个新的say方法

    • 但是大量的对象创建的say方法都是一样的方法,可以实现共享方法

    • 将say方法在全局作用域中创建

    • // 在全局作用域中定义
      function fun(){
      	alert(this.name);
      }
      
      function Box(name,age){
      	this.name = name,  
      	this.age = age,
      	// 向对象中添加方法  节省了大量的空间
      	this.say = fun;
      }
      var box1 = Box('bob',12);
      var box2 = Box('tom',13);   
      
      console.log(box1.say == box2.say); // true
      
      

原型对象

  • 引出原因:

    • 将say方法在全局作用域中定义
    • 污染了命名空间,在全局作用域中不安全,有局限
  • 原型:prototype

    • 我们所创建的每一个函数解析器都会向函数中添加一个属性prototype

    • 这个属性对应着一个对象,这个对象就是我们说的原型对象

    • 普通函数调用prototype没有任何作用

    • 当函数以构造函数调用时,它所创建的对象中都会有一个隐含的属性

      • 指向该函数的原型对象,我们可以通过__proto__来访问该属性

        function Box(){
        	
        }
        
        var box = new Box();
        console.log(Box.prototype);
        console.log(box.__proto__);
        console.log(box.__proto__ == Box.prototype ); // true
        
    • 原型对象相当于一个公共的区域,所有同一个类的实例都以访问到这个原型对象

    • 当我们访问对象的一个属性或方法时,它会先在对象的自身中寻找,如果没有则回去原型对象中去查找

    • 在这里插入图片描述

    • 这样接解决构造函数中,防止污染去全局中的命名空间

    • function Box(name,age){
      	this.name = name,  
      	this.age = age
      }
      Box.prototype.a = 123;
      Box.prototype.say = function(){this.name}
      var box1 = Box('bob',12);
      var box2 = Box('tom',13);   
      console.log(box1.say == box2.say); // true
      box1.say(); // bob 去原型对象中取
      
      // hasOwnProperty()来检查对象自身中是否含有该属性
      console.log(box1.hasOwnProperty('age'); // true
      console.log(box1.hasOwnProperty('a');  // false
      
  • 总结:以后我们在创建构造函数时,可以将这些对象共有的属性和方法,同一添加到构造函数的原型对象中,不会影响全局作用域

扩展原型对象

原型对象也是对象,它也有原型

  • 知道找到Object原型停止,如果在Object中仍然找不到我们使用对象的属性或者方法时,则会返回undefined
console.log(box1.__proto__.hasOwnProperty("hasOwnProperty")); // false
console.log(box1.__proto__..__proto__.hasOwnProperty("hasOwnProperty")); // true

toString() 方法:
当我们直接在页面中打印一个对象,实际上是输出的对象的toString()方法的返回值

可以改变返回值

function Box(name,age){
	this.name = name,  
	this.age = age
}

var box1 = Box('tonm',12);
box1.toString = function(){
	return 'hello world';
}
var res = per.toString();
console.log(res); // 控制台将会返回'hello world' ,而不是[object Object]

box1.toString = function(){
	return "Box[name="+this.name+",age="+this.age+"]";
}
console.log(box1); // 这样就可以打印具体的信息

// 修改原型对象中的toString()方法,这样以后创建的对象返回的值都会改变
Box.prototype.toString = function(){
	return "Box[name="+this.name+",age="+this.age+"]";
}

垃圾回收(GC)

程序运行时间长了,就会产生垃圾,这些垃圾积攒之后,会导致程序运行速度缓慢

我们需要一个垃圾回收机制,来处理运行程序中的产生的垃圾

当一个对象没有任何的变量或者属性对它引用,此时将无法操作该对象

这种垃圾太多,会占用大量的内存空间,导致程序运行时间变慢,必须进行清理

在Js中有自动的垃圾回收机制,自动将垃圾对象从内存中销毁,浏览器引擎处理

var obj = new Object();
obj = null;// 浏览器就可以识别

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42992704/article/details/105042533
今日推荐