‘new‘一下?

本文解析了构造函数与普通函数的区别,重点介绍了构造函数的使用方法及其内部机制,包括如何通过new关键字创建对象,以及如何手动实现new操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了更好的理解后面的内容,我们先来了解一些前置知识吧!

构造函数和普通函数的区别

构造函数:

使用一个函数来初始化对象,并配合new使用,则我们称这个函数为构造函数

普通函数

作为一个函数,除了构造函数之外就是普通函数了,详细大家用的比我熟练

构造函数和普通函数的区别

语法上没有区别!!!唯一的区别就是使用上的区别,使用上如何区别二者呢?使用了函数前面有一个new关键字,那就是构造函数,只要记住这一点就行了!

普通函数怎么使用呢?我就不在关公面前耍大刀了

进行分析new的过程,主要有以下几点

  • 创建一个新的对象
  • 把obj的__proto__指向fn的prototype,实现继承
  • 改变this的指向,执行构造函数、传递参数,fn.apply(obj,)或者 fn.call()
  • 返回新的对象obj

我们来看一下构造函数怎么使用吧!

function Person(name, age){
    this.name = "codingkid";
    this.age = 18;
}
var person = new Person();

  • 创建一个空对象
var person = {}
  • this变量指向对象p
Person.call(p)

关于call的用法并不难,可以去找一些参考资料

  • person除了有了Person函数中定义的变量外,还继承了Person()的原型,也就是可以使用Person()中原型的变量和方法,
person._proto_ = Person.prototype

由此可看构造函数就是比普通函数多了些操作,这些多的操作无疑和new关键字有很大的关系

不过需要细想几个问题

  • 第一个是关于this的问题,进行了上述过程后,构造函数中的this绑定了person对象,但普通函数却没有绑定对象,其实函数本质上也就相当于一个对象的属性,在全局下声明的函数相当于省略了window,不过是window的一个属性,所以调用时会指向window,在其他对象中声明的函数可类似此过程。
  • 构造函数会返回一个新的对象,所以不会在构造函数中使用return语句,如果使用了return语句,则会根据return值的类型而有所不同,原本没有如return会返回一个对象,对象是一个应用类型,所以当显示使用return返回应用类型的话,会生效,否则会失效,依旧返回声称的对象。普通函数的return正常用就行了。
实现new

手动实现

        var New =function(fn){
            var obj={};
            obj.__proto__=fn.prototype;
            // 将 arguments 对象转为数组
            var args = [].slice.call(arguments);
            //去除构造函数
            args.shift();
            // 执行构造函数并改变this对象
            var result = fn.apply(obj, args);            
            if(Object.prototype.toString.call(result)=="[object Object]" ){
                return result
            }else{
                return obj;
            }
        }   

测试

       var New =function(fn){
            var obj={};
            obj.__proto__=fn.prototype;
            // 将 arguments 对象转为数组
            var args = [].slice.call(arguments);
            //去除构造函数
            args.shift();
            // 执行构造函数并改变this对象
            var result = fn.apply(obj, args);            
            if(Object.prototype.toString.call(result)=="[object Object]" ){
                return result
            }else{
                return obj;
            }
        }    
 
        var Fn=function(sex){
            this.name='hty';
            this.sex=sex;
        }
        //返回一个对象
        var Fn1=function(){
            this.name='hml';
            return {
                name:'hty1'
            }
        }
        //返回非对象
        var Fn2=function(){
            this.name='hty3';
            return 1000
        }
        const fn=New(Fn,'123');
        console.log(fn.name);//hty
        console.log(fn.sex);//123
        const fn1=New(Fn1)
        console.log(fn1.name);//hty1
        const fn2=New(Fn2)
        console.log(fn2.name);//hty1

这里我写了一个例子,大家可以看看

<script>
    /*
    @author: zft
    @title: 如何实现一个 new
    @data:2020.10.5
    */
    function Dog(name) {
        this.name = name
        this.say = function () {
            console.log('name = ' + this.name)
        }
    }
    function Cat(name) {
        this.name = name
        this.say = function () {
            console.log('name = ' + this.name)
        }
    }
    function _new(fn, ...arg) {
        const obj = {}; //创建一个新的对象
        obj.__proto__ = fn.prototype; //把obj的__proto__指向fn的prototype,实现继承
        fn.apply(obj, arg) //改变this的指向
        return Object.prototype.toString.call(obj) == '[object Object]'? obj : {} //返回新的对象obj
    }
 
    //测试1
    var dog = _new(Dog,'aaa')
    dog.say() //'name = aaa'
    console.log(dog instanceof Dog) //true
    console.log(dog instanceof Cat) //true
    //测试2
    var cat = _new(Cat, 'bbb'); 
    cat.say() //'name = bbb'
    console.log(cat instanceof Cat) //true
 
</script>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值