关于原型链的那点事

前几日学习原型链的一些知识,今天在这里总结下继承的一些学习姿势

继承是什么?

总的来说对象的一个新类,从现有的类中派生,这个过程称之为继承。
继承的好处:减少重复的代码,比如父类已经提供的方法,子类可以直接使用,不必再去实现。


不过JS的继承不像其他面向对象语言的继承有着诸如“父类”和“子类”的概念,父类的的属性和方法子类可以继承而不必重写,只需要写出新增或者改写的内容。JS是基于对象的语言,没有类的概念,所以,要想实现继承,就需要用js的原型链或者用 apply 和 call 方法。


有几种常见创建对象的方式? 举例说明?

  • 直接创建。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var show={
    name:"z-one",
    age:"23",
    say:function(){
    console.log("my name is:"+"sss");
    }
    }
    var show1={
    name:"acorn",
    age:"22",
    say:function(){
    console.log("my name is:"+"sss");
    }
  • 构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var show=function(name,age){
    this.name=name;
    this.age=age;
    this.say=function(){
    console.log("my name is:"+this.name)
    }
    }
    var p1=new show("acorn","23"),
    p2=new show("zqy","24");
    p2.say();
    p1.say();
  • 工厂模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function show(name,age){
    var o={
    name:name,
    age:age,
    say:function(){
    console.log("myname is:"+name)
    }
    }
    return o;
    }
    var p1=show("acorn","23"),
    p2=show("z-one","22")
  • 原型模式

    1
    2
    3
    4
    5
    6
    7
    8
    function show(){};
    show.prototype.name="acorn";
    show.prototype.age="22"
    show.prototype.say=function(){
    console.log("my name is:"+this.name)
    }
    var p1= new show(),
    p2= new show()
  • 原型和构造函数相结合

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var show=function(name,age){
    this.name=name;
    this.age=age;
    }
    show.prototype.say=function(){
    var _this=this;
    console.log("my name is:"+_this.name)
    }
    var p1=new show("acorn","22"),
    p2=new show("Z-one","21");

下面两种写法有什么区别? (难度:*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('饥人谷', 2)
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}

Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('若愚', 27);

//第一种写法是 构造函数的方式创建实例,这样会使得每个实例都罕有printName 这个方法。相对第二种比较占用内存,
而第二种是用构造函数,和原型模式相结合方式,这样会让所创建的实例对象都公用一个printName 方法,相比第一种比较节省内存,但是因为所创建的实例对象printName方法的指针都指向一个位置,当改变printName方法时,所有对应的实例中的printName方法都会发生改变。

Object.create 有什么作用?兼容性如何?如何使用?

Object.create 是什么?

 Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。使得后者完全继承前者的属性,前者成为后者的原型。  

如何使用

例如

1
2
3
4
5
6
7
8
9
10
11
function show(name,age){
this.name=name;
this.age=age;
}
show.prototype.say=function(){

console.log("my name is:"+this.name);

}
var p=new show("acorn",23);
var p1=Object.create(p)

兼容性:

凡实现ECS5标准的浏览器,都能使用,IE9以上


hasOwnProperty有什么作用? 如何使用?

hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性。如果有,返回true,否则返回false

  • 该方法属于Object对象,由于所有对象都是Object的一个实例,因此几乎所有的对象都可以使用该方法。

  • 此方法不会检查对象的原型链中是否存在该属性,该属性只有是对象本身的一个成员才会返回true。

    如何使用

    例如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function show(){
    this.name="acorn";
    this.age=23;
    }
    show.prototype={
    say:function(){
    console.log("my name is:"+this.name);
    },
    sade:function(){
    console.log("测试下")
    }
    }
    var p=new show();
    console.log(p.hasOwnProperty("name"));//true
    console.log(p.hasOwnProperty("age"));//true
    console.log(p.hasOwnProperty("say"));//false
    //say 方法继承自原型链,因此为false
    当然如果要查看对象(包括原型链)是否具备指定的属性,可以用in操作符
    console.log("say" in p);//true
    console.log("name" in p)//true

关于Object.create的 polyfill的内部实现

1
2
3
4
5
6
7
8
9
10
11
12
13
function create(obj){
if(Object.create){
return Object.create(obj);
}else {
function show(){};
show.prototype=obj;
return new show();
}
}

var obj = {a: 1, b:2};
var obj2 = create(obj);
console.log(obj2.a);

如下代码中call的作用是什么?

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name, sex){
this.name = name;
this.sex = sex;
this.say=function(){
console.log(this.name)
}
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的 call 有什么作用
this.age = age;
}
//这里的作用是 把erson的作用域强行变为当前函数的作用域.让构造函数Person在这个作用域下执行.

补全代码,如何实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Person(name,sex){
this.name=name;
this.sex=sex;
}

Person.prototype.getName=function(){
console.log(this.name);
}

function Male(name,sex,age){
Person.call(this,name,sex);
this.age=age;
}
Male.prototype=Object.create(Person.prototype);
Male.prototype.getAge=function(){
console.log(this.age);
}

var p=new Male("acorn","男",23);

dialog 弹窗功能

在线预览
github 查看