node学习笔记04 模块(附加js原型学习解释)

1.外部访问局部变量,函数。

NodeJS包可以向外暴露很多需要的变量,函数等语法:

   exports.msg = msg;

   exports.showinfo = showinfo;

使用者只需要需要接受整个包,相当于增加了一个顶层变量:

var foo = require(“./ test / foo.js”)

执行的执行console.log(foo.js)   

默认变量名等于包名。一个包就相当于一个类,能够直接。函数。变量名的方式取值。

节点中,JS文件和JS文件,用出口需要状语从句来构建成网状结构。不是靠HTML统一在一起的。

2.一个JS中描述了一个类。

module.exports =构造函数名的方式向外暴露一个类。

1)js文件中,提供了函数,供其他使用。只需要暴露函数就行了.exports.msg = msg

2)js文件中,描述了一个类.module.exports = People

 

 

效果如下

 

 

3)如果需要(“foo.js”)没有写./,不是相对路径。是一个特殊的路径,是默认从node_module中暴露。

     注意:上图使用new foo而不是新人。

4)如果需要(“foo”的的)则是在node_modules中FOO的文件夹下面的index.js去寻找。

     如果FOO里面没有索引,JS就会报错。

补充学习:

1.proototype是什么?

1)JS中的对象

JS中每个数据类型都是对象(除了零和未定义的),而每个对象都继承自另外一个对象,后者称为“原型”(原型)对象(类比的的的java中的父类) ,只有零除外,它没有自己的原型对象。最顶层的是Object.prototype中中中,即对象构造函数的原型属性指向的那个对象

原型解决的问题: js中一个类的构造函数中的方法,新出来的对象没办法共享原型对象的属性和方法。(相当于java中的新出来的对象是不一样的).prototype来定义属性,就可以被新出来的实例对象所共享属性方法(共享也就是说他们的这个属性值如果同样参数值就相同)。

  看一个最简单的一个例子。

function Person(){

  this.name = 'Keith';
}

var boy = new Person();
console.log( body.name ); //"Keith"

构造函数的缺点

      所有的实例对象都可以继承构造函数中的属性和方法。但是,同一个对象实例之间,无法共享属性。

function Person(name,height){

this.name=name;

this.height=height;

this.hobby=function(){

return 'watching movies';

}

}

var boy=new Person('keith',180);

var girl=new Person('rascal',153);

console.log(boy.name); //'keith'

console.log(girl.name); //'rascal'

console.log(boy.hobby===girl.hobby); //false

 上面代码中,一个构造函数的人生成了两个对象实例的男孩和女孩,并且有两个属性和一个方法。但是,它们的爱好方法是不一样的也就是说,每当你。使用新来调用构造函数放回一个对象实例的时候,都会创建一个嗜好方法。这既没有必要,又浪费资源,因为所有爱好方法都是同样的行为,完全可以被两个对象实例共享。

2)原型属性的作用:

为了解决构造函数的对象实例(子类)之间无法共享原型对象(父类)属性的缺点,JS提供了原型属性。

通过构造函数生成对象实例时,会将对象实例的原型指向构造函数的原型属性。每一个构造函数都有一个原型属性,这个属性就是对象实例的原型对象。

function Person(name,height){

this.name=name;

this.height=height;

}

Person.prototype.hobby=function(){

return 'watching movies';

}

var boy=new Person('keith',180);

var girl=new Person('rascal',153);

console.log(boy.name); //'keith'

console.log(girl.name); //'rascal'

console.log(boy.hobby===girl.hobby); //true

  上面代码中,如果将hobby方法放在原型对象上,那么两个实例对象都共享着同一个方法。我希望大家都能理解的是,对于构造函数来说,prototype是作为构造函数的属性;对于对象实例来说,原型是对象实例的原型对象。所以原型即是属性,又是对象。

 

3)原型链原型链

     对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型对象本身对于对象实例来说也是对象,它也有自己的原型,所以形成了一条原型链(原型链)比如),一个对象是b对象的原型,b对象是ç对象的原型,以此类推。所有一切的对象的原型顶端,都是的Object.prototype中,即对象构造函数的原型属性指向的那个对象。

  当然,Object.prototype中中对象也有自己的原型对象,那就是没有任何属性和方法的空对象,而空对象没有自己的原型。

1 console.log(Object.getPrototypeOf(Object.prototype)); //null

2 console.log(Person.prototype.isPrototypeOf(boy)) //true

  原型链(prototype chain)的特点有:

    答:读取对象的某个属性时,JavaScript的的引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找如果直到最顶层的Object.prototype中中还是找不到,则返回不确定的。

    B:如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overiding)。

    C:一级级向上在原型链寻找某个属性,对性能是有影响的所寻找的属性在越上层的原型对象,对性能的影响越大如果寻找某个不存在的属性,将会遍历整个原型链。

  看概念可能比较晦涩,我们来看一个例子。但是理解了概念真的很重要。

var arr=[1,2,3];

console.log(arr.length); //3

console.log(arr.valueOf()) //[1,2,3]

console.log(arr.join('|')) //1|2|3

   上面代码中,定了一个数组ARR,数组里面有三个元素。我们并没有给数组添加任何属性和方法,可是却在调用长度,加入(),的的valueOf()时,却不会报错!!

  长度属性是继承自Array.prototype的,属于原型对象上的一个属性。加入方法也是继承自Array.prototype的,属于原型对象上的一个方法。这两个方法是所有数组所共享的。当实例对象上没有这个长度属性时,就会去原型对象查找。

  的的valueOf方法是继承自Object.prototype中中的。首先,ARR数组是没有的的valueOf方法的,所以就到原型对象Array.prototype查找。然后,发现Array.prototype对象上没有的的valueOf方法。最后,再到它的原型对象的Object.prototype中查找。

  来看看Array.prototype对象和Object.prototype中中对象分别有什么属性和方法。

console.log(Object.getOwnPropertyNames(Array.prototype))

//["length", "toSource", "toString", "toLocaleString", "join", "reverse", "sort", "push", "pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf", "forEach", "map", "filter", "reduce", "reduceRight", "some", "every", "find", "findIndex", "copyWithin", "fill", "entries", "keys", "values", "includes", "constructor", "$set", "$remove"]

console.log(Object.getOwnPropertyNames(Object.prototype))

// ["toSource", "toString", "toLocaleString", "valueOf", "watch", "unwatch", "hasOwnProperty",

 

4)构造属性(逆向继承,PS:自己便于理解)

关键词:A.prototype.constructor === A === a.constructor

      原型对象有一个构造属性,默认指向原型对象所在的构造函数。

function A(){};

console.log(A.prototype.constructor===A) //true

  要注意的是,原型是构造函数的属性,而构造则是构造函数的原型属性所指向的那个对象,也就是原型对象的属性。注意不要混淆。

  由于构造属性是定义在原型(原型)对象上面,意味着可以被所有实例对象继承。

function A(){};

var a=new A();

console.log(a.constructor); //A()

console.log(a.constructor===A.prototype.constructor);//true

  上面代码中,一个是构造函数甲的实例对象,但是一个自身没有构造器属性,该属性其实是读取原型链上面的A.prototype.constructor属性。

构造属性的作用(思路):

 答:分辨原型对象到底属于哪个构造函数

function A(){};

var a=new A();

console.log(a.constructor===A) //true

console.log(a.constructor===Array) //false

    上面代码表示,使用构造属性,确定实例对象一个的构造函数是A,而不是阵列。

 B:从实例新建另一个实例

function A(){};

var a=new A();

console.log(a.constructor===A) //true

console.log(a.constructor===Array) //false

 上面代码中,一个是构造函数甲的实例对象,可以从a.constructor间接调用构造函数。

 C:调用自身的构造函数成为可能

function A(){};

var a=new A();

console.log(a.constructor===A) //true

console.log(a.constructor===Array) //false

 d:提供了一种从构造函数继承另外一种构造函数的模式

function Father() {}

function Son() {

Son.height.constructor.call(this);

}

Son.height = new Father();

上面代码中,父亲和儿子都是构造函数,在儿子内部的这种上调用父,就会形成儿子继承父亲的效果。

 

补充:的的instanceof运算符

 的的instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。

function A() {};

var a = new A();

console.log(a instanceof A); //true

  因为的的instanceof对整个原型链上的对象都有效,所以同一个实例对象,可能会对多个构造函数都返回真。

function A() {};

var a = new A();

console.log(a instanceof A); //true

console.log(a instanceof Object); //true

 注意,的的instanceof对象只能用于复杂数据类型(数组,对象等),不能用于简单数据类型(布尔值,数字,字符串等)。

var x = [1];

var o = {};

var b = true;

var c = 'string';

console.log(x instanceof Array); //true

console.log(o instanceof Object); //true

console.log(b instanceof Boolean); //false

console.log(c instanceof String); //false

  此外,空和不确定的都不是对象,所以的instanceof总是返回假。

console.log(null instanceof Object); //false console.log(undefined instanceof Object); //false

  利用的的instanceof运算符,还可以巧妙地解决,调用构造函数时,忘了加新命令的问题。

function Keith(name,height) {

if (! this instanceof Keith) {

return new Keith(name,height);

}

this.name = name;

this.height = height;

}

  上面代码中,使用了的的的instanceof运算符来判断函数体内的这个关键字是否指向构造函数基思的实例,如果不是,就表明忘记加新的命令,此时构造函数会返回一个对象实例,避免出现意想不到的结果。

本人小白一枚,文章如有不严谨或者错误还请各位大神指出,欢迎大家讨论转载交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值