龙空技术网

javascript构造函数.成员函数详解

Java邦邦 18

前言:

当前咱们对“韩顺平js笔记”可能比较注意,大家都想要了解一些“韩顺平js笔记”的相关内容。那么小编同时在网络上网罗了一些对于“韩顺平js笔记””的相关知识,希望朋友们能喜欢,咱们一起来学习一下吧!

1.★类—如何定义类

讲了this后,我们类(对象原型)的定义就全面了一步,如图:

特别说明:

① this.属性名 公开属性,可以通过 对象名.属性名 来直接访问。

② var 属性名 私有属性,只能通过对象的内部函数来访问。

这里给大家举一个例说明,因为还没讲对象的函数,因此大家可能还不能很好的理解,这里只是给大家一个结论!(后面详细讲解)

2.对象—对象(成员)函数的初步介绍

在某些情况下,我们要需要定义对象函数。

比如人对象:除了有一些属性外(成员变量表示的年龄,姓名……),我们人对象还有一些行为比如:可以说话,跑步……,通过学习,我们人还可以做算术题。

这是就要用函数才能完成。

现在要对Person对象完善:

①添加speak函数,输出我是一个好人

②添加jisuan函数,可以计算从1+...+1000的结果

③修改jisuan函数,该方法可以接收一个数n,计算从1+...+n的结果

④添加add成员函数,可以计算两个数的和

1)对象——成员函数(方法)

① 比如:我们希望对象不但有属性,还希望他有行为。

② 行为在程序中要靠函数来体现

function Person(name,age){

//这个就是使用传入的实际参数,去初始化属性

this.name=name;

this.age=age;

//输出自己的名字

③ 这里this.就是一个公开的函数,函数名是show

④ 有一个麻烦事,先点出来。

⑤ 这样的方式有一个弊病,你用这样的方式分配一个函数,那么每个对象都有show这段函数代码。

⑥ 如p1有,p2也有等等,在一定程度上效率会有以一点影响,创建对象需要时间,这个问题怎么解决,在后面讲解。

⑦ 这样去分配函数,会使每一个Person对象实例,都有一段这样的show函数代码,也就是show这个函数不会放在一个所谓的代码区让所有对象共享,而是每一个对象都会有一段这样的代码,这就造成一种浪费了,当然在对象不多的情况下,也无所谓,一旦对象用完了就会被垃圾回收给回收了。

⑧ 如果连这点浪费也要避免的话,就要用原型的方式来解决。在后面会讲解。

⑨ 当然,this.show类似的方法在开发中也有用到。

this.show=function(){

document.writeln("名字="+this.name);

this要带上,如果不带this,就会认为name是另外一个变量

公开方法访问公开变量,必须要加this,这一点在公开与私有章节有说明 }

//添加jisuan函数,可以计算从1+...+1000的结果

this.jisuan=function(){

var res=0;

for(var i=1;i<=1000;i++){

res+=i;

}

return res;

}

//改进jisuan函数,可以计算从1+...+n的结果

this.jisuan2=function(n){

var res=0;

for(var i=1;i<=n;i++){

res+=i;

}

return res;

}

}

var p1=new Person("宋江",90);

p1.show();

document.writeln("<br/> res="+p1.jisuan());

document.writeln("<br/> res="+p1.jisuan2(10));

对象——成员函数

2)给一个对象添加(指定)函数的几种方式

读作:给属性赋了一个函数

配合前面那一种,还有后面的原型,一共4种

第一种:

function 类名(){

this.属性;

}

var 对象名=new 类名();

function 函数名(){

//执行

}

对象名.属性名=函数名;

对象名.属性名();

① 这样就相当于把 函数赋给 对象名.属性名,此时这个属性就表示一个函数

② 调用

第二种:

对象名.属性名=function 函数名(){

//代码

}

对象名.属性名(); //调用

1.★方式1

function Person(){

this.name="abc";

this.age=900;

}

function show1(){

window.alert("hello"+this.name);

}

动态分配函数,这样太灵活了,有时候,有点麻烦

//创建一个p1对象

var p1=new Person();

//把show1函数,给p1.abc,共享一个指针

p1.abc=show1; 没有括号

① 这样就相当于把show1的函数指针给它了,这个时候大家是共享的一个了,不是每个对象都有这个show1,不是每个对象都指向show1了,对比上面的demo1.html

② 把原来写在里面的show1函数,写在外面了,仅此而已

③ 如果给括号:p1.abc=show1(),则是把undefined给了abc属性

p1.abc(); //调用

javascript的语法特别灵活,不在里面写,而是在外面写了函数,然后再分配给他,就好像动态分配一个对象属性一样,动态分配一个函数,这是允许的。灵活是把双刃剑。

2.★带括号和不带括号的区别★

① 如果是p1.abc=show1;没有括号就是把函数本身交给p1.abc这个属性值,this会起作用,即helloabc。

② 如果是p1.abc=show1();有括号就是把show1函数的返回值交给p1.abc这个属性,即hello;

没有

函数本身

函数本身

有()

返回值

执行

function Person(){

this.name="abc";

this.age=900;

}

function show1(){

window.alert("hello"+this.name);

}

var p1=new Person();

p1.abc=show1; //把show1本身给了p1.abc属性,相当于在Person类中定义

① p1.abc(); //输出helloabc

② window.alert(p1.abc);

没有括号,不是p1.abc()这样的,输出function show1这个整个函数,打印函数本身

也可以理解为:带()执行;

不带本身

③ window.alert(p1.abc());

还会打出caojianbang

为什么还会输出undefined?

带括号,因为需要执行,所以不能知道数据类型

输出运行的函数,都是undefined

④ window.alert(show1);

同理和上面一样,同样没有括号,把整个function show1整个函数打印出来

⑤ window.alert(show1());

先输出hello,再输出undefined,show1的返回值。

分析过程和3,一样

⑥ ★★★p1.bcd=show1();

Window.alert(p1.bcd);

输出hello

(韩顺平没讲到)???

???疑问:按道理说没有返回值,为什么会输出

难道alert里面的内容属于返回值

之前结论是对的,确实没有返回值,而输出是因为,函数得运行,才能得到返回值

是过程中导致的

把show1函数的返回值给P1.bcd属性,

为什么没有this.name呢了,此时show1函数仅仅传递结果,

对于show1函数来讲,它不知道this是指向谁

3.★方式2

function Person(){

this.name="abc";

this.age=900;

}

var p1=new Person();

p1.abc=function show1(){

window.alert("hello"+this.name);

}

p1.abc();

function Person(){

this.name="abc";

this.age=900;

}

var p1=new Person();

//这个相当于把show1函数本身交给p1.abc属性了

//如同这样定义

//function Person(){

// this.name="abc";

// this.age=900;

// this.abc=function(){

// window.alert("hello"+this.name);

// }

//}

p1.abc=function show1(){

window.alert("hello"+this.name);

}

p1.abc();//输出helloabc

4.方式1和方式2的区别:

① 在方式1中,show1好多属性都可以用,如p2.abc=show1;

② 在方式2中,直接把函数给p1.abc了。

③ 而在方式2中,相当于function show1被p1.abc给独占了,如果p2.abc也要用,你还得把show1函数从新再写,不如在方式1中可以直接p2.abc=show1;

5.究竟用那种方法呢:

① 写在类定义中最通用

② 学了原型方式,不过最好还是用原型

③ 其他的两种方式要知道

6.★经典案例1

function Person(){

this.name="abc1";

this.age=900;

}

function show1(){

window.alert("hello+"+this.name); //这个this是谁在调用它,一定要看清楚了

}

var p1=new Person();

p1.abc=show1;

show1();

输出hello,在这里,this是window在调用,那么this就是window,但window的name没有值

输出hello,这样直接调用的话,虽然没有找到this.name她也不再输出了,js引擎一看this.name什么都没有就不输出了。

想看输出undefined,请看下面的语句,更好理解。

document.writeln在调试打印很重要

document.writeln(show1());//先输出hello,然后又输出undefined,此时的this指的是window,而window的name属性没有

7.★经典案例2

function Person(){

this.name="abc2";

this.age=900;

}

var name="北京";

function show1(){

window.alert("hello"+this.name);

}

var p1=new Person();

p1.abc=show1;

p1.abc(); //输出helloabc2

show1(); //输出hello北京

输出hello北京,window的name属性的值定义了,var name="北京";

★★★★★从上面可以更加深刻的认识,this,谁调用的this。

8.★经典案例3

function Person(){

this.name="abc";

this.age=900;

this.abc=function(v1,v2){

window.alert(this.name+" "+this.age+" "+v1+" "+v2);

}

}

var p1=new Person();

p1.abc();

输出 abc 900 undefined undefined;

① 调的起来,以函数名称调函数,大不了就值拿不到

② 虽然没有传入参数,但是函数是可以调用起来的,只是遇到 v1和v2会undefined

p1.abc("北京","天津"); //输出 abc 900 北京 天津

var p2=new Person();

p2.abc(); //输出 abc 900 undefined undefined

p2.abc("南京","东京"); //输出 abc 900 南京 东京

//p1 p2 每个对象创建的对象属性函数不一样

9.★经典案例4

看看下面的代码,会输出什么呢

function Person(){

this.name="abc";

this.age=900;

this.abc=function(v1,v2){

window.alert(this.name+" "+this.age+" "+v1+" "+v2);

}

}

var p1=new Person();

p1.name="中国";

p1.abc("北京","天津");

var p2=new Person();

p2.abc("南京","东京");

① 这里是动态添加,如果有了,就会将原来的给替换

② 这里主要是看p1.name会不会把this.name冲掉,

这里会把p1中的name属性冲掉。类中的this.name是一个公开的属性,p1.name确实是访问这个属性了,原先确实是abc,但是给你赋了一个新值过后,abc就会被冲掉了,变成了中国。p1.name的的确确是动态添加了,js引擎会首先检测下,p1里面是否已经有了name这个属性值,如果有的话,就在p1这个对象中,把原来的值冲掉,用新值代替,这样更容易理解。

3)原型的方法来添加方法1.问题

此时就讲到了在demo1.html中的麻烦事,如在类中定义,this.show=function(){};这种定义方法,在有些时候,老板或项目经理会对你不满意,因为你每创建一个p1,p2,p3...每一个都会有这个show属性,就相当于每个对象实例都有this.show=function(){};这段代码。

2.内存分析图

3.★证明两个对象的方法代码不共享,

下面的例子不充分,可能是用一个指针指到那里去的

每个对象有独立的空间,方式可以看一下

判断两个对象的方法属性不同

==双等判断地址是否相同

4.解决方案

再看使用另外一种方法来给类添加方法! 使用原型的方法来添加, 这是第四种了。前面已经讲解了三种了:

(1).在类定义的内部

(2)外部添加如上面的:p1.abc=show1;

(3)外部添加如上面的:p1.abc=function show1(){}

function Dog(){

}

var dog1=new Dog();

dog1.shout=function(){

window.alert("小狗");

}

dog1.shout();

var dog2=new Dog();

dog2.shout(); //这里会报错

========>>>

function Dog(){

}

var dog1=new Dog();

Dog.prototype.shout=function(){

window.alert("小狗");

}

① 希望所有对象,都共享某个函数

② 使用prototype[绑定在类上的] 去绑定一个函数给shout

③ 如果我们对象很多,就不是件好事,因为每一个对象实例都带有这段代码。

④ 所有的类都有这个属性,叫prototype是原型,prototype上绑定的所有都是共享的,独一份的。

⑤ 这个属性,是函数属性

⑥ 这里就是让所有的Dog对象共享同一个shout属性function(){}

dog1.shout();

var dog2=new Dog();

dog2.shout();//这里ok

判断地址相同

window.alert(dog1.shout==dog2.shout); //true

① 类是有描述信息的,称为代码区

② 绑定了函数,就会存放到代码区,进行分散共享

③ 堆中的shout会指向代码区

④ 一定程度上节省空间

5.★内存分析6.扩展

var dog3=new Dog();

var dog4=new Dog();

window.alert("dog3==dog4"+(dog3==dog4));//false,dog3和dog4指向的堆区地址不一样

var dog5=dog4; // 让dog5指向dog4

window.alert("dog4==dog5"+(dog4==dog5));//true,dog4和dog5指向的堆区地址一样

7.结论:

① 前面的三种方法有一个问题:那就是每个对象,独占函数代码

② 这样如果对象很多,则会影响效率

③ js设计者,给我们提供了另一个方法 原型法 prototype

8.★补讲:==号的作用

①当 ==的两边是字符串的时候,则比较内容 相等否

②如 ==的两边是数字,则数的大小是否相等

③如 ==的两边是对象 或者是对象函数,则比较地址是否相同

记不住,和不知道是两回事,记住最常用的,记不住的,学会查找。

1

字符串

内容

2

数字

大小

3

对象

地址

4

对象函数

地址

标签: #韩顺平js笔记 #js中的add函数