资讯专栏INFORMATION COLUMN

关于javaScript面向对象写法以及new操作符

endless_road / 1495人阅读

摘要:属性属性当我们通过关键字构造函数实例化创建一个对象时,这个对象里面含有属性,属性指向构造函数属性以及属性下面的对象。

众所周知,JavaScript是一门面向对象的操作语言,而我们想要用JavaScript对象化写法的时候,不得不提出一个操作符,叫做new操作符,那么不用new操作符和用new操作符有什么区别呢?

1.用new和不用new的区别

首先,我们去看下new在JavaScript里面的用法,按照javascript语言精粹中所说,如果在一个函数前面带上new来调用该函数,那么将创建一个隐藏连接到该函数的prototype成员的新对象,同时this将被绑定到那个新对象上。这句话说得很抽象,我们根据代码来理解。

function foo(){
                this.name = "John";
                this.age = 23; 
                var born = 1993;
                return this.age;
            }
//没用new关键字
var foo2 = foo();
console.log(foo2);//23
//用new关键字
var foo3 = new foo();
console.log(foo3);//foo {name: "John", age: 23}

通过上面的代码可以明显看出区别,当我们不用new关键字的时候我们只是把foo函数运行了一遍,如果有返回值就就获得这个返回值,没有返回值就输出underfind,只是简单的函数运行一遍而已。
但是当我们用new关键字的时候,我们就可以看到不同了,new关键字是生成一个对象,并且生成的对象里面的属性是foo函数公有属性(即只有用this关键字定义的变量),而忽略掉私有变量(即用var定义的变量)和函数返回值,这样上面关于new关键字的解释就好理解了,即通过new操作符创建一个连接到foo函数的对象,对象里包含foo函数里面所有属性和方法。这就是new关键字的作用,并且this是指向我们当前的对象foo3.

2.JavaScript面向对象里面的三个关键属性 2.1 prototype(原型)对象

js语言没有类这个概念,所以提出用原型来代替类来实现js面向对象写法。js规定每个函数都具有prototype对象,并且prototype对象在函数外部是可以访问的,可以通过"prototype.xxx"来为当前函数增加属性和方法,所以prototype属性可以理解为当我们想为这个函数添加属性或者方法时我们可以在prototype属性下面添加,而不需要去改变构造函数的代码。

function foo(){
            this.name = "John";
            this.age = 23; 
            var born = 1993;
            return this.age;
        }
foo.prototype.ccc = function(){
    console.log(this.name);
}
console.log(foo.prototype);//Object {}

chrome的运行结果如下图:

可以看到foo函数里的prototype是可以访问的,并且我们所添加的函数是在prototype对象里的。这样,我们就可以通过prototype属性向对象添加属性和方法。

2.2constructor(构造器)属性

在上面的我们看到chrome浏览器运行结果的图中,我们打印foo函数prototype对象可以发现里面包含有constructor属性,所以constructor属性的是prototype对象下的一个属性,即:

function foo(){
            this.name = "John";
            this.age = 23; 
            var born = 1993;
            return this.age;
    }
console.log(foo.prototype.constructor == foo);//true

可以看到原型对象下的constructor事指向当前构造函数的,函数在创建时就会自动生成constructor属性来指向当前对象,实例化对象时constructor属性也会一并继承到新的对象下面。

2.3__proto__属性

__proto__属性当我们通过new关键字构造函数实例化创建一个对象时,这个对象里面含有__proto__属性,__proto__属性指向构造函数prototype属性以及prototype属性下面的对象。即:

function foo(){
                this.name = "John";
                this.age = 23; 
                var born = 1993;
                return this.age;
            }
    foo.prototype.ccc = function(){
        console.log(this.name);
    }
    
    var foo2 = new foo();
    console.log(foo2.__proto__ == foo.prototype)//true
    console.log(foo2.__proto__)//Object {ccc:function(),constructor: foo()}

console.log(foo2.__proto__)在chrome里的运行结果如下图:

可以看到__proto__对象是等于foo.prototype对象的,并且foo.prototype对象下面的方法和属性都已经在实例化对象foo2下的__proto__下面了。

3.js的原型链

js没有其他面向对象编程语言的多态的概念,所以如何实现多态的概念。这时,js提出了原型链的概念,通过原型链来实现扩展方法以及属性的功能。看如下代码

 function foo(){
                this.name = "John";
                this.age = 23; 
                var born = 1993;
                return this.age;
            }
foo.prototype.ccc = function(){
    console.log(this.name);
}

var foo2 = new foo();
foo2.ccc();//John
var foo3 = new foo();
foo3.ccc();//John
//修改foo3对象下面ccc方法
foo3.ccc = function(){
    console.log(this.age);
}

foo3.ccc();//23

从上面代码实例化对象时新的对象不仅克隆了构造的函数属性和方法,也克隆了构造函数原型下的属性以及方法,在foo3对象中,当我们没有修改ccc方法时,函数会在当前对像下查找,没查找到就会去原型对象里查找该方法,在原型对象里找到了ccc方法,打印出this.name为“John”,当我们重写了ccc方法时,ccc方法就已经foo3当前对象下面了,所以在当前对象下面找到了ccc方法,运行ccc方法,并且停止查到,不会再继续向下查,所以js原型链会遵循就近查找原则,如果查找不到当前方法会到原型下去查找,查找不到再去原型下面的原型去查找,直到查找到所有原型为止。
我们答应下foo3对象,console.log(foo3),在chrome运行结果如下图:

可以看出foo3对象下面拥有一个ccc方法,并且在原型对象下面也拥有一个ccc方法,遵循就近查找原则,会找到foo3对象下面的ccc方法,而不会去查到原型对象里的ccc方法。所以通过js的原型链可以修改对象的属性和方法。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79931.html

相关文章

  • javascript面向对象的常见写法与优缺点

    摘要:我们通过表单验证的功能,来逐步演进面向对象的方式对于刚刚接触的朋友来说,如果要写一个验证用户名,密码,邮箱的功能,一般可能会这么写表单验证全局全局全局这种写法,从功能上来说没有什么问题,但是在团队协作的时候,会造成覆盖全局变量的问题,那要大 我们通过表单验证的功能,来逐步演进面向对象的方式. 对于刚刚接触javascript的朋友来说,如果要写一个验证用户名,密码,邮箱的功能, 一...

    Ajian 评论0 收藏0
  • Javascript面向对象从入门到重新入门--关于继承

    摘要:这个构造函数的不管从调用方式还是内部写法就都很有的感觉,但是从用途上来说,它其实更靠近的概念是中的工厂方法。到这里,所有关于继承的东西讲完了,接下来准备准备说说当中的封装 所谓的对象,就是抽象化的数据本身 一个面向对象转向面向原型的困惑 我发现Javascript这门语言每次翻开都会带给人新感受,尤其是看完其他语言的面向对象再来看它,但是如果你也是过来人就一定记得教科书里面冗长乏味的...

    3fuyu 评论0 收藏0
  • 从一个组件的实现来深刻理解 JS 中的继承

    摘要:回到最开始的组件问题那么,说了这么多面向对象,现在回到最开始的那个组件的实现如何用面向对象来实现。总结从一个组件出发,一步一步爬坑,又跑去介绍中的面向对象,如果你能看到最后,那么你就可动手一步一步实现一个了,纯调侃。 其实,无论是写什么语言的程序员,最终的目的,都是把产品或代码封装到一起,提供接口,让使用者很舒适的实现功能。所以对于我来说,往往头疼的不是写代码,而是写注释和文档!如果接...

    Lin_R 评论0 收藏0
  • 浅谈JavaScript面向对象

    摘要:不必在构造函数中定义对象实例的信息。其次,按照一切事物皆对象的这饿极本的面向对象的法则来说,类本身并不是一个对象,然而原型方式的构造函数和原型本身也是个对象。第二个问题就是在创建子类型的实例时,不能向超类型的构造函数中传递参数。 前言 对象(Object)应该算是js中最为重要的部分,也是js中非常难懂晦涩的一部分。更是面试以及框架设计中各出没。写这篇文章,主要参考与JavaScrip...

    cyixlq 评论0 收藏0
  • JS前端面试总结

    摘要:春招季如何横扫面试核心考点基础版前端面试之路二基础整理的继承和的继承有什么区别的继承时通过或构造函数机制来实现。作用创建私有变量,减少全局变量,防止变量名污染。异步浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。 春招季如何横扫 Javascript 面试核心考点(基础版)?前端面试之路二(javaScript基础整理) ES5的继承和ES6的继承有什么区别 ES5的继承时通过...

    ThinkSNS 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<