function Parent(name, id){
this.id = id;
this.name = name;
this.list = ['a'];
this.printName = function(){
console.log(this.name);
}
}
Parent.prototype.sayName = function(){
console.log(this.name);
};
function Child(name, id){
Parent.call(this, name, id);
// Parent.apply(this, arguments);
}
Child.prototype = new Parent();
var child = new Child("jin", "1");
child.printName(); // jin
child.sayName() // jin
var a = new Child();
var b = new Child();
a.list.push('b');
console.log(b.list); // ['a']
SSR就是一台服务器,可以利用 SSR 在远程的服务器上配置 SSR,使其能够成为 SSR 节点,这样本地电脑或者其它设备利用 SSR 节点实现 VPN 或者远程上网及游戏加速等方面。ShadowsocksR(简称 SSR)是 Shadowsocks 分支,在 Shadowsocks 的基础上增加了一些数据...
一、Visual Studio Code下载地址:https://code.visualstudio.com/微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目:一个运行于 Mac OS X、Windows和 Linux 之上的,针对于编写现代 Web 和云应用的跨平台源代码编辑器。Visual Stud...
1.原型链继承
实现方式:将子类的原型链指向父类的对象实例
原理:子类实例child的
__proto__
指向Child的原型链prototype,而Child.prototype指向Parent类的对象实例,该父类对象实例的__proto__
指向Parent.prototype,所以Child可继承Parent的构造函数属性、方法和原型链属性、方法优点:可继承构造函数的属性,父类构造函数的属性,父类原型的属性
缺点:无法向父类构造函数传参;且所有实例共享父类实例的属性,若父类共有属性为引用类型,一个子类实例更改父类构造函数共有属性时会导致继承的共有属性发生变化;实例如下:
2.构造函数继承
实现方式:在子类构造函数中使用call或者apply劫持父类构造函数方法,并传入参数
原理:使用call或者apply更改子类函数的作用域,使this执行父类构造函数,子类因此可以继承父类共有属性
优点:可解决原型链继承的缺点
缺点:不可继承父类的原型链方法,构造函数不可复用
3.组合继承
原理:综合使用构造函数继承和原型链继承
优点:可继承父类原型上的属性,且可传参;每个新实例引入的构造函数是私有的
缺点:会执行两次父类的构造函数,消耗较大内存,子类的构造函数会代替原型上的那个父类构造函数
4.原型式继承
原理:类似Object.create,用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象,结果是将子对象的
__proto__
指向父对象缺点:共享引用类型
5.寄生式继承
原理:二次封装原型式继承,并拓展
优点:可添加新的属性和方法
6.寄生组合式继承
原理:改进组合继承,利用寄生式继承的思想继承原型
优点:
原型链继承
我们使用原型继承时,主要利用sub.prototype=new super,这样连通了子类-子类原型-父类。
借用构造函数
1.避免了引用类型的属性被所有实例共享
2.可以在 Child 中向 Parent 传参
组合继承
1、利用构造函数和原型链的方法,可以比较完美的实现继承
js继承方式的缺点
1、原型链继承
构造函数原型上的属性在所有该构造函数构造的实例上是共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上。
2.借用构造函数
方法都在构造函数中定义,每次创建实例都会创建一遍方法。
3、组合继承
借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承
4、原型式继承
包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。
5、寄生式继承
跟借用构造函数模式一样,每次创建对象都会创建一遍方法。
第一种,prototype的方式:
这种方式最为简单,只需要让子类的prototype属性值赋值为被继承的一个实例就行了,之后就可以直接使用被继承类的方法了。
prototype 属性是啥意思呢? prototype 即为原型,每一个对象 ( 由 function 定义出来 ) 都有一个默认的原型属性,该属性是个对象类型。
并且该默认属性用来实现链的向上攀查。意思就是说,如果某个对象的属性不存在,那么将通过prototype属性所属对象来查找这个属性。如果 prototype 查找不到呢?
js会自动地找prototype的prototype属性所属对象来查找,这样就通过prototype一直往上索引攀查,直到查找到了该属性或者prototype最后为空 (“undefined”);
例如上例中的one.view()方法,js会先在one实例中查找是否有view()方法,因为没有,所以查找man.prototype属性,而prototype的值为person的一个实例,
该实例有view()方法,于是调用成功。
第二种,apply的方式:
注意:如果apply参数为空,即没有参数传递,则通过 new Array() 、[] 来传递,null 无效。
第三种,call+prototype的方式:
call方式的实现机制却要多一条 man.prototype = new person(); 为啥呢?
那是因为call方法只实现了方法的替换而没有作对象属性的复制操作。
google Map API 的继承就是使用这种方式。
上面总结了三种继承方式的实现。但是每种方法都有其优缺点。
假如父类是这样的:
子类应该如何设计,使子类man在创建对象的同时传递参数到父类person,prototype的继承方式就不适用了,
必须采用apply或者call的方式了:
但是用apply方法也还是有缺点的,为什么?在js中,我们有个非常重要的运算符就是”instanceof”,该运算符用来比较某个对向是否为某种类型。
对于这个例子,one实例除了是man类型,也应该是person类型,但是apply方式继承之后,one却不属于person类型,即(one instanceof person)的值为false。
经此种种,最好的继承方式就是call+prototype方式了,之后你可以试一下(one instanceof BaseClass)的值是否为true。
第三种继承方式也有缺陷:子类new对象时要传一遍父类所需的参数,而且会重现父类中的属性和方法,下面这种继承方式才是完善的:
类式继承就像java的继承一样,思想也比较简单:在子类型构造函数的内部调用超类型构造函数
一、原型链继承
/* 原型链:
JavaScript中实现继承最简单的方式就是使用原型链,将子类型的原型指向父类型的实例即可,即“子类
型.prototype = new 父类型();”,实现方法如下: */
//为父类型创建构造函数
function SuperType () {
this.name = ['zc','ls','ww'];
this.property = true;
}
//为父类型添加方法
SuperType.prototype.getSuperValue = function() {
return this.property;
};
//为子类型创建构造函数
function SubType() {
this.test = ['a','b','c','d'],
this.subproperty = false
}
//子类型的原型指向父类型的实例
SubType.prototype = new SuperType();
//给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function() {
return this.subproperty;
}
// 测试代码
var instance1 = new SubType();
instance1.name.push('yzy');
instance1.test.push('e');
console.log(instance1);
console.log(instance1.getSuperValue()); //true
console.log(instance1.getSubValue()); //false
console.log(instance1.name);
console.log(instance1.test);
var instance2 = new SubType();
console.log(instance2);
console.log(instance2.name);
console.log(instance2.test);
var instance3 = new SuperType();
console.log(instance3);
/* 缺点:原型链代码存在的第一个问题是由于子类型的原型是父类型的实例,也就是子类型的原型中包
含的父类型的属性,从而导致引用类型值的原型属性会被所有实例所共享。以上代码的
instance1.name.push('yzy');就可以证明此问题的存在。而原型链的第二个问题就是:在创建子类型
的实例时,不能向超类型的构造函数中传递参数。因此我们在实际开发中,很少单独使用原型链。 */
二、借用构造函数
/* 借用构造函数:
为了解决原型链中存在的两个问题,开发人员开始使用一种叫做借用构造函数的技术来解决原型链中存在
的问题。这种技术的实现思路也挺简单,只需要在子类型的构造函数内调用父类型的构造函数即可。别忘
了,函数只不过是在特定环境中执行代码的对象,因此可以通过apply()或call()方法执行构造函数。代
码如下: */
//为父类型创建构造函数
function SuperType(name) {
this.name = name;
this.color = ['green','red'];
this.property = true;
this.testFun = function() {
console.log('你真棒!!');
}
}
//为父类型添加方法
SuperType.prototype.getSuperValue = function() {
return this.property;
}
//为子类型创建构造函数
function SubType(name) {
SuperType.call(this, name);
this.test = ['a','b','c','d'];
this.subproperty = false;
}
//给子类型添加方法,一定要在实现继承之后,否则会将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function() {
return this.subproperty;
}
//测试代码
var instance1 = new SubType(['zc','ls','ww']);
instance1.name.push('hello');
instance1.test.push('5');
instance1.color.push('blue');
instance1.testFun();
console.log(instance1.name);
// console.log(instance1.getSuperValue()); //报错
console.log(instance1.test);
console.log(instance1.getSubValue());
console.log(instance1.color);
var instance2 = new SubType('yzy');
instance2.testFun(); //你真棒!!
console.log(instance2.name); // yzy
// console.log(instance2.getSuperValue()); //报错
console.log(instance2.test); // a,b,c,d
console.log(instance2.getSubValue()); // false
console.log(instance2.color); // green , red
/* 缺点:可以看到以上代码中子类型SubType的构造函数内通过调用父类型"SuperType.call(this,
name);",从而实现了属性的继承,也可以在子类型创建实例的时候为父类型传递参数了,但新的问题又
来了。可以看到我在父类型的构造函数中定义了一个方法:testFun,在父类型的原型中定义了一个方
法:getSuperValue。可是在实例化子类型后仍然是无法调用父类型的原型中定义的方法
getSuperValue,只能调用父类型中构造函数的方法:testFun。这就同创建对象中只使用构造函数模式
一样,使得函数没有复用性可言。考虑到这些问题,借用构造函数的技术也是很少单独使用的。 */
三、组合继承
/* 组合继承(原型链+借用构造函数):
组合继承就是结合使用原型链与借用构造函数的优点,组合而成的一个模式。实现也很简单,既然是结
合,那当然结合了两方的优点,即原型链继承方法,而在构造函数继承属性。具体代码实现如下:*/
// 为父类型创建构造函数
function SuperType(name) {
this.name = name;
this.color = ['pink', 'yellow'];
this.property = true;
this.testFun = function () {
console.log('你真棒!!');
}
}
// 为父类型添加方法
SuperType.prototype.getSuerperValue = function () {
return this.property;
}
// 为子类型创建构造函数
function SubType(name) {
SuperType.call(this, name);
this.test = ['h1', 'h2', 'h3', 'h4'];
this.subproperty = false;
}
// SubType.prototype = new SuperType();
//解决相同属性出现在原型中的问题,_proto_来源部分有偏差
SubType.prototype = SuperType.prototype;
SubType.prototype.constructor = SubType;
// 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function () {
return this.subproperty;
}
/* 以下为测试代码示例 */
var instance1 = new SubType(['yzy', 'Jack', 'Nick']);
instance1.name.push('hello');
instance1.test.push('h5');
instance1.color.push('blue');
instance1.testFun(); // 你真棒!!
console.log(instance1);
console.log(instance1.name); // yzy,Jack,Nick,hello
console.log(instance1.getSuerperValue()); // true
console.log(instance1.test); // h1,h2,h3,h4,h5
console.log(instance1.getSubValue()); // false
console.log(instance1.color); // pink,yellow,blue
var instance2 = new SubType('yz');
instance2.testFun(); // 你真棒!!
console.log(instance2);
console.log(instance2.name); // yz
console.log(instance2.getSuerperValue()); // true
console.log(instance2.test); // h1,h2,h3,h4
console.log(instance2.getSubValue()); // false
console.log(instance2.color); // pink,yellow
//缺点:若再添加一个子类型,给其原型单独添加一个方法,那么其他子类型也同时拥有了这个方法,因
为它们都指向同一个父类型的原型
四、原型式继承
/* 原型式继承:
原型式继承的的实现方法与普通继承的实现方法不同,原型式继承并没有使用严格意义上的构造函数,而是借
助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。具体代码如下: */
/* 原型式继承 */
function object(o) {
function F() { }
F.prototype = o;
return new F();
}
var person = {
name: 'yzy',
friends: ['bbc', 'Nick', 'Tim']
}
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Bob');
var anotherPerson2 = object(person);
anotherPerson2.name = 'Jack';
anotherPerson2.friends.push('Rose');
console.log(person.friends); // bbc,Nick,Tim,Bob,Rose
console.log(anotherPerson2);
console.log(anotherPerson);
/* 缺点:所有实例都会继承原型上的属性; 无法实现复用 */
五、寄生式继承
/* 原型式继承 */
function object(o) {
function F() { }
F.prototype = o;
return new F();
}
/* 寄生式继承 */
function createAnother(original) {
var clone = object(original);
clone.sayHi = function () {
alert('hi');
}
console.log(clone);
return clone;
}
var person = {
name: 'wuyuchang',
friends: ['yzy', 'Nick', 'Rose']
}
var anotherPerson = createAnother(person);
anotherPerson.sayHi();
/* 重点:就是给原型式继承外面套了个壳子。
优点:没有创建自定义类型,因为只是套了个壳子返回对象,这个函数顺理成章就成了创建的新对象。
缺点:没用到原型,无法复用。 */
六、寄生组合式继承
/* 寄生组合式继承 */
// 为父类型创建构造函数
function SuperType(name) {
this.name = name;
this.color = ['pink', 'yellow'];
this.property = true;
this.testFun = function () {
console.log('你真棒!!');
}
}
// 为父类型添加方法
SuperType.prototype.getSuerperValue = function () {
return this.property;
}
// 为子类型创建构造函数
function SubType(name) {
SuperType.call(this, name);
this.test = ['h1', 'h2', 'h3', 'h4'];
this.subproperty = false;
}
//
function SubType2(name) {
SuperType.call(this, name);
this.test = ['s1', 's2', 's3', 's4'];
this.subproperty = false;
}
//
function object(o) {
function F() { }
F.prototype = o;
return new F();
}
/* 寄生组合式继承
基本所有问题都已解决,暂时没有发现问题, 现今的完美解决方案*/
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
// SubType.prototype = new SuperType();
inheritPrototype(SubType, SuperType);
inheritPrototype(SubType2, SuperType);
// 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,则方法为空
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
SubType.prototype.bbc = function() {
console.log('哈哈哈');
};
/* 以下为测试代码示例 */
var instance1 = new SubType(['yyy', 'Jack', 'Nick']);
instance1.name.push('hello');
instance1.test.push('h5');
instance1.color.push('blue');
instance1.testFun(); // 你真棒!!
instance1.bbc();
console.log(instance1);
console.log(instance1.name); // yyy,Jack,Nick,hello
console.log(instance1.getSuerperValue()); // true
console.log(instance1.test); // h1,h2,h3,h4,h5
console.log(instance1.getSubValue()); // false
console.log(instance1.color); // pink,yellow,blue
var instance2 = new SubType2('yzy');
instance2.testFun(); // 你真棒!!
// instance2.bbc(); //报错
console.log(instance2);
console.log(instance2.name); // yzy
console.log(instance2.getSuerperValue()); // true
console.log(instance2.test); // s1,s2,s3,s4
// console.log(instance2.getSubValue()); // 报错
console.log(instance2.color); // pink,yellow
/* 解决了组合继承的问题 */
(end)
第一种,prototype的方式:
这种方式最为简单,只需要让子类的prototype属性值赋值为被继承的一个实例就行了,之后就可以直接使用被继承类的方法了。
prototype 属性是啥意思呢? prototype 即为原型,每一个对象 ( 由 function 定义出来 ) 都有一个默认的原型属性,该属性是个对象类型。
并且该默认属性用来实现链的向上攀查。意思就是说,如果某个对象的属性不存在,那么将通过prototype属性所属对象来查找这个属性。如果 prototype 查找不到呢?
js会自动地找prototype的prototype属性所属对象来查找,这样就通过prototype一直往上索引攀查,直到查找到了该属性或者prototype最后为空 (“undefined”);
例如上例中的one.view()方法,js会先在one实例中查找是否有view()方法,因为没有,所以查找man.prototype属性,而prototype的值为person的一个实例,
该实例有view()方法,于是调用成功。
第二种,apply的方式:
注意:如果apply参数为空,即没有参数传递,则通过 new Array() 、[] 来传递,null 无效。
第三种,call+prototype的方式:
call方式的实现机制却要多一条 man.prototype = new person(); 为啥呢?
那是因为call方法只实现了方法的替换而没有作对象属性的复制操作。
google Map API 的继承就是使用这种方式。
1.原型链继承
我们使用原型继承时,主要利用sub.prototype=new super,这样连通了子类-子类原型-父类。
缺点:构造函数原型上的属性在所有该构造函数构造的实例上是共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上。
2.构造函数继承
在构造子类构造函数时内部使用call或apply来调用父类的构造函数
优缺点:实现了属性的私有化,但是子类无法访问父类原型上的属性。
3.组合继承
利用构造函数和原型链的方法,可以比较完美的实现继承
4.寄生继承
即将sub.prototype=new super改为sub.prototype=Object.creat(supper.prototype),避免了组合继承中构造函数调用了两次的弊端。
优点:
原型链继承
我们使用原型继承时,主要利用sub.prototype=new super,这样连通了子类-子类原型-父类。
借用构造函数
1.避免了引用类型的属性被所有实例共享
2.可以在 Child 中向 Parent 传参
组合继承
1、利用构造函数和原型链的方法,可以比较完美的实现继承
js继承方式的缺点
1、原型链继承
构造函数原型上的属性在所有该构造函数构造的实例上是共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上。
2.借用构造函数
方法都在构造函数中定义,每次创建实例都会创建一遍方法。
3、组合继承
借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承
4、原型式继承
包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。
5、寄生式继承
跟借用构造函数模式一样,每次创建对象都会创建一遍方法。
相关问题推荐
相对前几年来说,要高上不少了,毕竟入行的人也是越来越多了,基础的工作对应想要参与的人群基数越来越大,但是对于高端人才的需求还是很多,人才还是相对稀缺性的。所以,想要学web或者其他技术也一样,别等,别观望。web前端就业方向特别多包括web前端开发...
相对定位和绝对定位是定位的两种表现形式,区别如下:一、主体不同1、相对定位:是设置为相对定位的元素框会偏移某个距离。2、绝对定位:absolute 脱离文档流,通过 top,bottom,left,right 定位。二、特点不同1、相对定位:在使用相对定位时,无论是否进行移...
抓包(packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包也经常被用来进行数据截取等。抓包可以通过抓包工具来查看网络数据包内容。通过对抓获的数据包进行分析,可以得到有用的信息。目前流行的...
常用的前端框架有Bootstrap框架、React框架、Vue框架、Angular框架、Foundation框架等等
前端是目的就业前景非常不错的一个计算机技术,但是自学的话还是有一定难度的,网络上自学是碎片化的,同时互联网技术跟新换代快,自己的话比较吃力也学习不到最新的技术。
SSR就是一台服务器,可以利用 SSR 在远程的服务器上配置 SSR,使其能够成为 SSR 节点,这样本地电脑或者其它设备利用 SSR 节点实现 VPN 或者远程上网及游戏加速等方面。ShadowsocksR(简称 SSR)是 Shadowsocks 分支,在 Shadowsocks 的基础上增加了一些数据...
1、代码判断xAxis: {type: 'time',splitLine: {show: false},interval: 3600, // 设置x轴时间间隔axisLabel: {formatter: function(value, index) {return liangTools.unix2hm(value)}}},首先要把xAxis 显示类型设置成time,然后设置对应X轴......
计算机培训方向比较多,建议找适合自己的方向选择培训编程类:JAVA、WEB、Python、C/C++、C#等测试类:软件测试运维类:云计算、网络安全设计类:UI设计、3D建模等
HTML5 + CSS + JavaScript 开发 跨平台重用代码
采用rem单位自动响应,并提供独有栅格化系统快速定义宽高、边距节省css代码量,同时总结各大型移动端网页,提供一套ui颜色搭配规范,尺寸规范,字体规范等。
iView UI、ioni、SUI
jQTouch
如果只是普通的移动端用vue react 或者dva 如果是要编译成小程序什么的或者混生 就用uni-app(对应vue语法)taro(对应react) 或者纯原生 这个没有限制的,自己怎么舒服怎么来
因为可以运用在网页和小程序的开饭中,而且开源,用着便宜,企业都很喜欢
一、Visual Studio Code下载地址:https://code.visualstudio.com/微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目:一个运行于 Mac OS X、Windows和 Linux 之上的,针对于编写现代 Web 和云应用的跨平台源代码编辑器。Visual Stud...
jQuery自带淡入淡出效果 https://www.w3school.com.cn/jquery/jquery_fade.asp 看看这个