Keep on coding

JavaScript - 面向对象 - 继承性


这一节,主要讲解面向对象的继承,回顾上一节讲解到判断对象原型和实例对象的两种方法.废话不多说,直接上代码 !

继承 ==> 重点

  • 子对象–>父对象,Object是所有对象的父级
  • 一种把其他对象的属性和方法变为己有的方式
  • 通过继承可以提高代码的复用性和可维护性
  • 举例 : 动物 – 狗类 – 金毛狗类

    1.对于狗类来説:动物是它的父类型,而金毛狗类是它的子类型
    2.对于金毛狗类来説.狗类是它的父类型,动物类是它的超类型.

继承的两种方式

  • 接口继承
  • 实现继承
  • js中的继承:
    javaScript中继承只支持实现继承,实现继承主要依赖原型链来完成

Js中继承的几种实现方式

混入式继承

  • 示例代码1 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//1. 创建一个空的对象o
var o = {};
//2. 提供一个已经有的对象obj
var obj = {
name:"对象的属性",
age:20,
sayHello:function () {
console.log("hello");
}
}
//3. 混入式继承(把原有对象的所有属性和方法都拷贝给新的对象)
for(var k in obj)
{
o[k] = obj[k];
}
//4. 打印查看o对象
console.log(o);
//5. 如果属性的值是引用类型的,那么子对象和父对象共享一块数据,修改了某个对象对另外一个对象有影响
console.log(o.sayHello == obj.sayHello); //true
  • 示例代码2 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
//参数:
//第一个参数是目标对象
//第二个,第三个参数是要拷贝属性的对象
var o = {};
var obj1 = {name:"name"};
var obj2 = {age:20};
var obj3 = {car:{type:"飞船"}};
Object.assign(o,obj2,obj1,obj3);
console.log(o);
obj3.car.type = '汽车';
console.log(o);
</script>

原型式继承

  • 原型对象中的成员(属性|方法)可以被使用该构造函数创建出来的所有对象共享
  • 利用上面的性质,可以实现原型式的继承
  • 示例代码1 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
//1. 提供一个构造函数
function Person(name,age) {
this.name = name;
this.age = age;
}
//2. 设置原型对象的属性
Person.prototype.className = "逍遥派1班";
//3. 使用构造函数来创建原型对象
var p1 = new Person("张三",10);
var p2 = new Person("李四",20);
//4. 打印p1和p2对象中的className属性
console.log(p1.className);
console.log(p2.className);
//结论:对象p1和p2继承了构造函数原型对象中的属性className
//但是这并不是严格意义上的继承
</script>
  • 示例代码2 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
//1. 提供一个构造函数
function Person(name,age) {
this.name = name;
this.age = age;
}
//2. 设置原型对象的属性
Person.prototype = {
constructor:Person,
className:"逍遥派1班"
};
//3. 使用构造函数来创建原型对象
var p1 = new Person("张三",10);
var p2 = new Person("李四",20);
//4. 打印p1和p2对象中的className属性
console.log(p1.className);
console.log(p2.className);
//结论:对象p1和p2继承了构造函数原型对象中的属性className
//注意:使用原型替换的方式实现继承的时候,原有原型对象中的属性和方法会丢失
</script>

示例代码3 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script>
//1. 提供超类型|父类型
function SuperClass() {
this.name = 'SuperClass的名称';
this.showName = function () {
console.log(this.name);
}
}
//2. 设置父类型的原型属性和原型方法
SuperClass.prototype.info = 'SuperClass的信息';
SuperClass.prototype.showInfo = function () {
console.log(this.info);
};
//3. 提供子类型
function SubClass() {
}
//4. 设置继承(原型对象继承)
SubClass.prototype = SuperClass.prototype;
SubClass.prototype.constructor = SubClass;
var sub = new SubClass();
console.log(sub.name); //undefined
console.log(sub.info); //SuperClass的信息
sub.showInfo(); //SuperClass的信息
sub.showName(); //sub.showName is not a function
</script>
  • 存在的问题 :

    1.构造器属性指向(默认指向的是父构造函数)
    2.无法获得实例属性和方法,只能继承(获得)父构造函数原型对象的属性和方法

  • 扩展内置对象
    要给数组扩展一个name的属性和一个sayHello方法

  • 示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
//1. 创建数组对象
var arr = [1,2,3];
var arr2 = new Array(1,2,3);
console.log(arr2);
//2. 设置Array构造函数的原型对象
Array.prototype.name = "默认的名称";
Array.prototype.sayHello = function () {
console.log("hello");
};
console.log(arr.name); //默认的名称
console.log(arr2.name); //默认的名称
arr.sayHello(); //hello
arr2.sayHello(); //hello
//1.上面的方式可以达到扩展内置对象的效果,但不推荐这样去做
//2.遇到那种大项目可能需要多人合作一起开发,而且项目中的代码数量可能非常庞大
//3.如果大家都通过这种方式来扩展内置对象,那么日后必将难以管理,而且可能会出现方法被覆盖等安全问题
</script>
  • 安全的扩展内置对象

    核心过程
    1.提供一个构造函数(自定义)
    2.设置构造函数的原型对象为内置构造函数创建出来的对象

  • 示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//Array
function MyArray(){};
//设置原型对象
MyArray.prototype = new Array();
MyArray.prototype.des = "描述信息";
MyArray.prototype.logDes = function(){
console.log(this.des);
}
//使用自己的构造函数来创建对象
var myArr01 = new MyArray();
var myArr02 = new MyArray();
myArr01.push("123","abc");
console.log(myArr01);
console.log(myArr01.des);
function OtherArray(){};
OtherArray.prototype = new Array();
OtherArray.prototype.des = "描述信息";
OtherArray.prototype.logDes = function(){
console.log("------------");
}
var otherArr01 = new OtherArray();
var otherArr02 = new OtherArray();
console.log(otherArr01.des);
otherArr01.logDes();
  • 图解

**安全扩展内置对象**

原型链继承 ( 什么是原型链 ? )

  • 每个对象都是由构造函数创建出来的,因为每个对象都有构造函数
  • 每个构造函数都有一个与之对应的原型对象
  • 原型对象本身也是对象
  • 因此,原型对象也有自己的构造函数
  • 原型对象的构造函数也有自己的原型对象
  • 原型对象的构造函数的原型对象也是对象,所以它也有自己的构造函数
  • 原型对象的构造函数的原型对象的构造函数也有自己的原型对象。
    以上,形成一个链式的结构,就称为是原型链

  • 原型链的顶端是Object.prototype,Object.prototype本身也是一个对象,因此也有原型对象
    Object.prototype.__proto__ 是null

  • 原型链的搜索规则 :

    是向上查找,如果有直接使用,如果没有,继续向上查找.直到找到原型链的顶端
    原型链搜索的路径越长,查询属性所花费的时间就越多
    原则:就近原型

    **

  • 继承方法

    1.提供一个父构造函数
    2.提供子构造函数
    3.设置子构造函数的原型对象为父构造函数的一个实例对象
    4.在这个实例对象上面设置属性和方法

  • 示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script>
function A(){
this.age = 55;
this.showAge = function(){
console.log(this.age);
}
};
//设置A的属性和方法
A.prototype.logDes = function(){
console.log("des");
}
function B(){
};
//设置原型链继承
B.prototype = new A();
B.prototype.des = "des";
B.prototype.show = function(){
console.log("show");
};
var b1 = new B();
console.log(b1.age);
b1.showAge();
b1.logDes();
console.log(b1);
</script>
  • 复杂的原型链

    1.提供构造函数(4)
    2.设置属性和方法(建议:属性设置在实例上,方法设置在原型上)
    3.设置继承
    4.修正构造器属性

  • 示例代码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<script>
Animal.prototype.run = function(){
console.log("run");
}
function Animal(color){
this.color = color
}
Person.prototype = new Animal();
Person.prototype.eat = function(){
console.log("chi");
}
Person.prototype.constructor = Person;
function Person(){
this.name = "默认的名称"
}
Student.prototype = new Person();
Student.prototype.study = function(){
console.log("good good study, day day up");
}
Student.prototype.constructor = Student;
function Student(){
this.id = "20160501"
}
Boy.prototype = new Student();
Boy.prototype.lol = function(){
console.log("LoL");
}
Boy.prototype.constructor = Boy;
function Boy(){
this.sex = "男"
}
//创建对象
var boy = new Boy("红色");
console.log(boy);
</script>
  • 原型链继承的注意点

    1.注意必须要在设置子对象的原型属性和原型方法之前来实现继承
    2.在子对象的原型对象中可以设置同名的属性或方法,覆盖父对象的原型对象中的属性和方法
    3.原型链继承之后,使用字面量的方式来设置原型会导致之前的原型对象丢失

  • 示例代码1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
//注意点
//如果代码段2==>代码段1 则运行正常,,如果代码段1==>代码段2,则报错'eat方法不存在'
function Person() {};
Person.prototype.run = function () {
console.log('Person__run');
};
function Man() {};
//代码段1
Man.prototype.eat = function () {
console.log('Man__eat');
};
//代码段2
Man.prototype = new Person(); //设置原型链继承
var m = new Man();
m.run(); //Person__run
m.eat(); //Man__eat
//建议:在设置完原型链继承之后,再设置子对象原型对象上面的属性和方法,否则会丢失(之前的原型对象被切断)
</script>
  • 示例代码2 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
// 注意点2 && 注意点3
// 在子对象中(原型对象中)可以重写父对象中(原型对象中)的方法
// 子对象在调用的时候原型对象中的方法会覆盖父对象原型对象中的
// 方法,父类型的实例调用方法不受影响
function Person() {};
Person.prototype.run = function () {
console.log('Person__run');
};
function Man() {};
//代码段2
Man.prototype = new Person(); //设置原型链继承
Man.prototype.run = function () {
console.log('Man__run');
};
var m = new Man();
m.run(); //Man__run
var p = new Person();
p.run(); //Person__run
</script>

-示例代码3 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
// 在重写原型对象实现继承之后,不能使用字面量的方式来设置原型对象,
// 否则之前的原型继承关系会被切断
function Person() {};
Person.prototype.run = function () {
console.log('Person__run');
};
function Man() {};
//代码段2
Man.prototype = new Person(); //设置原型链继承
Man.prototype = {
eat:function () {
console.log('Man__eat');
}
}
var m = new Man();
m.eat(); //Man__eat
m.run(); //调用的方法不存在
</script>
  • 原型链继承存在的问题

    1.父类型实例属性会转换为子类型原型的原型属性,而如果父类型是实例属性是引用类型则会存在共享问题
    2.在创建子类型的实例时,不能向父类型的构造函数中传递参数

  • 示例代码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script>
//1. 提供父类型的构造函数
function SuperType() {
//2. 在构造函数中中设置实例属性,该属性为引用类型
this.family = ['哥哥','姐姐','爸爸','妈妈'];
};
//3. 提供子类型的构造函数
function SubType() {};
//4. 设置原型继承
SubType.prototype = new SuperType();
//5. 创建父类型的实例对象,并对内部的实例化属性进行修改
var subDemo1 = new SubType();
var subDemo2 = new SubType();
console.log(subDemo1);
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈
subDemo1.family.push('爷爷','奶奶');
alert(subDemo1.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶
alert(subDemo2.family); //哥哥,姐姐,爸爸,妈妈,爷爷,奶奶
//6. 如果父类型的实例属性中有引用类型,那么在子类型创建的实例对象中存在共享问题
</script>
  • Object.Create
  • 作用:创建对象,并且设置该对象的原型对象
  • 兼容性问题:ES5
  • 基本用法
  • 示例代码1 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
//JavaScript语言精粹
function create(o) {
var F = function () {};
F.prototype = o;
return new F();
}
var obj1 = create({name:"默认的名字"});
console.log(obj1);
//把参数(对象)作为新对象的原型对象
var obj = Object.create({name:"默认的名字"});
console.log(obj);
//需要考虑到浏览器兼容的问题
</script>
  • 实例代码2 : 若不兼容则动态添加create方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
var tmp = {age:20};
if (Object.create){
//如果有值那么就直接调用
var o = Object.create(tmp)
}
else{
Object.create = function () {
var F = function () {};
F.prototype = tmp;
var o = new F();
}
}
</script>
  • 示例代码3 : 使用函数来封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
function create(o) {
if (Object.create)
{
//如果有值那么就直接调用
return Object.create(o)
}else
{
var F = function () {};
F.prototype = o;
return F();
}
}
var a = create({name:"默认的名字",age:20});
console.log(a);
</script>
  • call && apply函数 ==> 重点

    1.这两个方法都是原型对象上面的方法 – 借用其他对象的方法
    2.call和apply两个函数的作用是一样的,都可以用来借用方法
    参数:
    第一个参数是调用该方法的对象(函数内部的this绑定的对象)
    后面的参数:
    call:参数列表
    apply:数组
    3.调用方法
    对象1.方法.call(调用方法的真正的对象,参数1,参数2,参数3);
    对象1.方法.apply(调用方法的真正的对象,[参数1,参数2,参数3..]);

  • 示例代码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
//console.log(Function.prototype);
var demo01 = {
name:"小偷",
showName:function(param1,param2){
console.log(this.name,param1,param2);
}
}
var demo02 = {
name:"我是老实人"
}
demo01.showName("小贼","毛贼");
demo01.showName.call(demo02,"江洋大盗","采花大盗");
demo01.showName.apply(demo02,["山贼","土匪"]);
</script>
  • 关于this

    1.javaScript中的this总是指向一个对象。
    2.调用方式 :
    2.1作为对象的方法来调用 this—>当前的对象
    2.2作为普通的函数调用 this—>window
    2.3作为构造函数和new使用 this—>构造函数内部新创建的对象
    2.4被call或者是apply调用(函数上下文调用) this—>第一个参数

  • 示例代码1 : 当函数作为对象的方法调用时,this指向该对象

1
2
3
4
5
6
7
8
9
10
<script>
var obj = {
name:"张三",
demoFunc:function () {
console.log(this == obj); //true
console.log(this.name); //张三
}
}
obj.demoFunc();
</script>
  • 示例代码2 : 当函数作为普通函数调用是,this总是指向全局对象
1
2
3
4
5
6
7
<script>
window.name = "window测试的name";
var funcName = function () {
console.log(this.name); //window测试的name
}
funcName();
</script>
  • 示例代码3: 使用new 构造函数创建对象调用,this总是指向内部默认创建并返回的对象
1
2
3
4
5
6
7
8
<script>
function Person() {
this.name = "默认的姓名"
}
var p1 = new Person();
console.log(p1.name); //默认的姓名
</script>
  • 实例代码4: Function.prototype.call或Function.prototype.apply调用
1
2
3
4
5
6
7
8
9
10
11
<script>
var obj = {
name:"张三",
getName:function () {
console.log(this.name);
}
}
obj.getName(); //张三
var obj2 = {name:"李四"};
obj.getName.call(obj2); //打印李四
</script>

借用构造函数继承

  • 借用构造函数实现继承:可以获得父构造函数中的实例属性,解决了传参的问题
  • 示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
function Person(name,age){
this.name = name;
this.age = age;
};
function Boy(bookName,name,age){
this.bookName = bookName;
//Person.call(this,"八戒",600); //借用构造函数
Person.call(this,name,age);
}
//创建对象
var boy = new Boy("水煮三国","悟空",600);
var boy02 = new Boy("大话西游","云风",40);
console.log(boy);
console.log(boy02);
</script>

组合(原型链 + 借用)继承

  • 借用构造函数实现继承:可以获得父构造函数中的实例属性
    Person.call(this,name,age)
  • 获得原型属性和方法 ( Boy.prototype = Person.prototype)
  • 组合继承:原型 + 借用构造函数

  • 示例代码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>
function Person(name,age){
this.name = name;
this.age = age;
};
Person.prototype.des = "描述信息";
Person.prototype.logDes = function(){
console.log(this.des);
};
function Boy(bookName,name,age){
this.bookName = bookName;
//Person.call(this,"八戒",600); //借用构造函数
Person.call(this,name,age);
}
//设置原型继承
//Boy.prototype = new Person();
Boy.prototype = Person.prototype;
//创建对象
var boy = new Boy("水煮三国","悟空",600);
var boy02 = new Boy("大话西游","云风",40);
console.log(boy);
console.log(boy02);
boy.logDes();
var p1 = new Person();
p1.logDes();
Boy.prototype.des = "描述信息-bOY";
boy.logDes();
p1.logDes();
</script>

深拷贝和浅拷贝

  • 示例代码 : 浅拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
var obj = {
name:"小花脸",
car:{
type:"客车"
}
};
var o = {};
for (var k in obj)
{
o[k] = obj[k];
}
console.log(o);
o.car.type = "银河战舰";
console.log(obj);
</script>
  • 深拷贝

    1.提供一个函数,两个参数(原对象,要拷贝属性的对象)
    2.在函数中先检查第一个参数是否有值,如果没有值那么就初始化一个空的对象
    3.for..in循环来变量参数2,
    3.1检查当前的属性值是什么类型
    3.2如果是值类型,那么就直接拷贝赋值
    3.3如果是引用类型,那么就再调用一次这个方法,去内部拷贝这个对象的所有属性

  • 示例代码 : 深拷贝封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<script >
var obj = {
name:"小花脸",
car:{
type:"客车",
},
friends:["1","2","3"]
};
//兼容性处理
if(typeof Array.isArray != "function") {
Array.isArray = function(obj){
return Object.prototype.toString.call(obj) == "[object Array]";
}
}
var o = {};
//deepCopy(o,obj);
function deepCopy(obj1,obj2) {
obj1 = obj1 || {};
for (var i in obj2)
{
if (obj2.hasOwnProperty(i))
{
if( typeof obj2[i] == "object")
{
//判断是数组还是对象
obj1[i] = Array.isArray(obj2[i])?[]:{};
//引用类型
deepCopy(obj1[i],obj2[i]); //函数调用
}else
{
//值类型
obj1[i] = obj2[i];
}
}
}
}
deepCopy(o,obj);
console.log(o);
//共享问题
//o.car.type = "小货车";
console.log(obj);
</script>

通过深拷贝实现继承

  • 完整的继承方案

    1.拥有父构造函数的实例属性
    2.拥有父构造函数的原型属性
    3.是相互独立的,彼此不受影响

  • 示例代码 :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    <script>
    if(typeof Array.isArray != "function") {
    Array.isArray = function(obj){
    return Object.prototype.toString.call(obj) == "[object Array]";
    }
    }
    function deepCopy(obj1,obj2) {
    obj1 = obj1 || {};
    for (var i in obj2)
    {
    if (obj2.hasOwnProperty(i))
    {
    if( typeof obj2[i] == "object")
    {
    //判断是数组还是对象
    obj1[i] = Array.isArray(obj2[i])?[]:{};
    //引用类型
    deepCopy(obj1[i],obj2[i]); //函数调用
    }else
    {
    //值类型
    obj1[i] = obj2[i];
    }
    }
    }
    }
    function Person(name,age){
    this.name = name;
    this.age = age;
    };
    Person.prototype.des = "描述信息";
    Person.prototype.car = {
    type:"汽车"
    }
    Person.prototype.logDes = function(){
    console.log(this.des);
    };
    function Boy(bookName,name,age){
    this.bookName = bookName;
    //Person.call(this,"悟空",600); //借用构造函数
    Person.call(this,name,age);
    }
    //设置原型继承
    //Boy.prototype = Person.prototype;
    deepCopy(Boy.prototype,Person.prototype); //把父构造函数原型对象上面的属性和方法全部拷贝一份给Boy
    //创建对象
    var boy01 = new Boy("水煮三国","悟空",600);
    var boy02 = new Boy("大话西游","云风",40);
    Boy.prototype.car.type = "火车";
    console.log(Boy.prototype);
    var p1 = new Person();
    console.log(p1.car.type);
    </script>

基本包装类型

  • String Number Boolean
  • 示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script>
//1. 创建字符串对象
var str1 = new String("demo01"); //object
var str2 = "demo01"; //string
var str3 = String("demo01"); //string(正确) | object
console.log(typeof str1);
console.log(typeof str2);
console.log(typeof str3);
//2. 创建数字对象
var num1 = new Number(10); //object
var num2 = 10; //number
var num3 = Number(20); //number
//3. 布尔类型的对象
var bool01 = new Boolean(true); //object
var bool02 = true; //boolean
var bool03 = Boolean(true);
console.log(typeof bool01);
//4. 特殊的创建方式
var str4 = new Object("demo01"); //object | string
var num4 = new Object(10);
var bool04 = new Object(true);
console.log(typeof str4);
</script>
  • 基本包装类型注意点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
var str1 = "demo01"; //string
var str2 = new String("demo01"); //object
var str3 = String("demo01");
console.log(str1 == str2); //true 转换
console.log(str1 === str2); //false
console.log(str1.length); //6 获得字符串的长度
//基本数据类型的值怎么能够访问属性呢?
//属性和方法只有对象才有
//为什么?
//字符串、数值以及布尔值在访问属性或者调用方法的时候
//1. 内部会隐式的创建一个对象,利用该对象来访问属性或者是调用方法
//2. 得到结果之后,把结果赋值给基本数据类型的值
//3. 销毁这个创建的对象
str1.des = "描述信息";
console.log(str1.des); //undefined
str2.des = "des";
console.log(str2.des); //des(正确的) | undefined
</script>
  • 总结

    1.变量的方式调用成功
    2.表达式的方式调用成功
    3.数值的方式调用失败

  • 示例代码 :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <script>
    Number.prototype.sum = function(param){
    return this + param;
    }
    var num1= new Number("10");
    var num2 = 30;
    console.log(num1.sum(2));
    console.log(num1.sum(33));
    console.log(num2.sum(44)); //可以调用吗? 74
    console.log((10).sum(11)); //可以调用吗? ()表达式 21
    console.log(10.sum(22)); //不可以调用
    </script>

附思维导图一张,希望能帮到各位 ! 如果图片不清晰的话 请下载到本地查看

JavaScript - 面向对象编程三