Javascript中的构造函数

Javascript中没有类,但可以把函数当类使,被用来当做类构造器的函数就叫构造函数

一、特点

1、定义时,函数名首字母大写
为了与普通函数区分开,建议首字母大写。
2、定义时,函数内部使用this定义属性或者方法。
3、定义时,默认不用return返回值
构造函数是不需要用return显式返回值的,默认会返回this,也就是新的实例对象。当然,也可以用return语句,返回值会根据return值的类型而有所不同。如果return的是五种简单数据类型:String,Number,Boolean,Null,Undefined,则忽视return值,依然返回this对象。如果return的是Object,那么不再返回this对象,而是返回return语句的返回值。
4、调用时,用new关键字
默认返回一个新对象实例,这个新对象具有构造函数定义的公有属性(特权属性)和公有方法(特权方法)。

二、基本模型

//定义
function Person(name,age){
  this.age = age;
  this.getAge = function(){
    console.log('实例方法,我的年龄是:'+ this.age);
  }
}
//调用
var p1 = new Person('Camille',25);
p1.getAge();//实例方法,我的年龄是:25。

等同于

function Person(name,age){
  var obj = new Object();
  obj.age = age;
  obj.getAge = function(){
    console.log('实例方法,我的年龄是:'+ obj.age);
  }
  return obj;
}
var p1 = Person("Camille",25);
p1.getAge();

三、深入分析

function Person(name,age){
  //私有成员属性
  var name = 'Camille';
  var sex = 'female';
  var self = this;
  //私有成员方法
  var getName = function(){
    console.log('我的名字是:'+ self.name);
  }

  //公有属性(特权属性)
  this.age = age;
  //公有方法(特权方法)
  this.getAge = function(){
    console.log('实例方法,我的年龄是:'+ this.age);
  }
}
Person.name = 'HouYi';
Person.getName2 = function(){
  console.log('我的名字2是:'+ this.name);
}
/**
 * 测试Person调用
 * 私有成员和公有成员都不能访问
 * 可以访问新定义的属性或方法
 */
console.log(Person.sex);//undefined,无法访问私有成员。
console.log(Person.name);//Person,也不是undefined,为啥不是HouYi,留个悬念。
Person.getName();//Person.getName is not a function,无法访问私有成员。
console.log(Person.age);//undefined,无法访问公有成员。
Person.getAge();//Person.getAge is not a function,无法访问公有成员。
Person.getName2();//我的名字2是:Person,可以访问新定义的getName2()
/**
 * 测试实例调用
 * 不能访问私有成员
 * 可以访问公有成员
 * 不能访问新定义的属性或方法
 */
var p1 = new Person('Camille',25);
console.log(p1.name);//undefined,无法访问私有成员。
console.log(p1.constructor.name);//Person,为啥不是HouYi,你猜。
p1.getName();//p1.getName is not a function,无法访问私有成员。
p1.constructor.getName();//p1.constructor.getName is not a function,无法访问私有成员。
p1.getAge();//实例方法,我的年龄是:25,可以访问公有成员。
p1.getName2();//p1.getName2 is not a function,不能访问新定义的getName2()

四、一些疑惑

/**
 * 1、Func()和new Func()的区别
 * Func()是普通函数,指向window;new Func()是构造的新函数,指向当前函数的实例。
 */
function Func(n){
  var name = n || 'Camille';
  console.log(name);
}
var f1 = Func();//Camille
console.log(f1); 
var f2 = new Func();//Camille
console.log(f2); 

/**
 * 2、new Func和new Func()的区别
 *  new运算符本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号。
 *  都是Func类的实例化,是等价的,只不过后者可以向函数传参数。
 */
var f3 = new Func;//Camille
console.log(f3);
var f4 = new Func('Houyi');//Houyi
console.log(f4);
/**
 * 3、return getName和return getName()的区别
 * 前者是引用,没有立即执行;后者会立即执行函数。
 */
function func(){
  var name = 'Camille';
  function getName(){
    console.log('我的名字是:'+ name);
  }
  return getName;//只是一个变量,引用,没有立即执行
}
func()();//我的名字是:Camille

function func(){
  var name = 'Camille';
  function getName(){
    console.log('我的名字是:'+ name);
  }
  return getName();//立即执行了
}
func();//我的名字是:Camille
/**
 * 4、func()和return func()的区别
 * 前者没有保存最后一次循环的值,后者保存了。
 */
var i = 0;
function func(){
    i++;
    if(i < 10){
        func();
    }else{
        return i;
    }
}
var temp = func();
console.log(temp); //undefined

var i = 0;
function func(){
    i++;
    if(i < 10){
        return func();
    }else{
        return i;
    }
}

var temp = func();
console.log(temp);//10

五、new的用途

new的作用,就是执行构造函数,返回一个实例对象。

1、使用new命令时,它后面的函数调用就不是正常的调用,而是依次执行下面的步骤:
  • 创建一个空对象,作为将要返回的对象实例
  • 将这个空对象的原型,指向构造函数的prototype属性
  • 将这个空对象赋值给函数内部的this关键字
  • 开始执行构造函数内部的代码
function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ param1) {
  // 将 arguments 对象转为数组
  var args = [].slice.call(arguments);
  // 取出构造函数
  var constructor = args.shift();
  // 创建一个空对象,继承构造函数的 prototype 属性
  var context = Object.create(constructor.prototype);
  // 执行构造函数
  var result = constructor.apply(context, args);
  // 如果返回结果是对象,就直接返回,则返回 context 对象
  return (typeof result === 'object' && result != null) ? result : context;
}

// 实例
var p1 = _new(Person, 'Camille', 28);

2、为了保证构造函数必须与new命令一起使用,下面提供两种方案告诉开发者不要忘了new。
A、在构造函数内部使用严格模式,即第一行加上use strict。

function Person(age){
  'use strict';
  this.age = age;
  this.getAge = function(){
    console.log('实例方法,我的年龄是:'+ this.age);
  }
}
Person(25);// TypeError: Cannot set property 'age' of undefined

上面代码的Person为构造函数,use strict命令保证了该函数在严格模式下运行。由于在严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错,因为JavaScript 不允许对undefined添加属性。
B、在构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象。

function Person(age){
  if (!(this instanceof Person)) {
    return new Person(age);
  }
/*
  if (!new.target) {
    throw new Error('请使用new命令调用!');
  }
*/
  this.age = age;
  this.getAge = function(){
    console.log('实例方法,我的年龄是:'+ this.age);
  }
}
Person(25).getAge() // 实例方法,我的年龄是:25
//(new Person(25)).getAge() // 实例方法,我的年龄是:25

 

转载于:https://www.cnblogs.com/camille666/p/js_constructor_function.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值