JavaScript 对象继承 OOP (三)
对象继承
#### 传统原型链式继承
function Grand(){};
Grand.prototype.name="grand";
let grand = new Grand();
Father.prototype=grand;
function Father(){}
let father = new Father();
Son.prototype=father;
function Son(){}
let son = new Son();
#### 借用构造函数 使用call/appply
function Father() { }
function Son() {
Father.call(this); // 调用父类构造函数
}
Son.prototype.print = function() {
Father.prototype.print.call(this);//只使用单个方法
}
// 子类继承父类的原型
Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;
#### 圣杯模式
let inherit =(function(){
let Interim =function Interim() {};
return function (Target,Origin){//继承源
Interim.prototype =Object.create(Origin);
Target.prototype = Interim.prototype;
//现在 可以 制定自己的私有属性,但是 constuctor 不是 原函数所一手动赋值回来,如果想要知道函数真正继承那个原型需要保存它
Target.prototype.constuctor = Target;
Target.prototype.yliluokka =Origin;
}
}())
#### 多重继承
function Fn1(){ }
function Fn2(){ }
function Son(){
F1.call(this);
F2.call(this);
}
//继承F1
Son.prototype =Object.create(Fn1.prototype);
//继承F2
Object.assign(Son.prototype,Fn2.prototype);
Son.prototype.constructor =Son;
let a =new Son();
### call,apply and bind difference
#### call and apply
function test() {}
//test() == test.call()
let obj ={};
Object.prototype.toString.call(obj) //"[object Object]"
//因为call 和 apply 会将函数中的this指向第一个参数
//相当于 obj.toString()
//返回数组中最大的数
let a = [1, 2, 4, 1, 15];
Math.max.apply(null, a) // //将数组的空元素变为undefined
Array.apply(null [1,,3,,4)//[1,undefined,3,undefined,4];
let obj={0: 1, length: 2}
Array.protetype.slice.apply(obj);//[1,undefined]
参数为空、null和undefined,则默认传入全局对象。
#### bind
let counter = {
count: 0,
inc: function () {
this.count++;
}
};
let func = counter.inc.bind(counter);
func();
counter.count //
let add = function (x, y) {
return x * this.m + y * this.n;
}
let obj = {
m: 2,
n: 2
};
let newAdd = add.bind(obj, 5); //将x 绑定为 5
newAdd(5) //
newAdd(1,5)//
第一个参数是null或undefined,等于将this绑定到全局对象
#### bind方法使用注意点
let counter = {
count: 0,
inc: function () {
'use strict';
this.count++;
}
};
function callIt(callback) {
callback();
}
callIt(counter.inc.bind(counter));
counter.count //
[1, 2, 3].slice(0, 1) // [1]
// 等同于
Array.prototype.slice.call([1, 2, 3], 0, 1) // [1] //将Array.prototype.slice变成Function.prototype.call方法所在的对象
//调用时就变成了Array.prototype.slice.call。 let slice = Function.prototype.call.bind(Array.prototype.slice);
Function.prototype.slice.call([1, 2, 3], 0, 1) // [1]
//slice([1, 2, 3], 0, 1) let push = Function.prototype.call.bind(Array.prototype.push);
let pop = Function.prototype.call.bind(Array.prototype.pop); let a = [1 ,2 ,3];
push(a, 4)
a // [1, 2, 3, 4] pop(a)
a // [1, 2, 3]
function f() {
console.log(this.v);
}
let o = { v: 123 };
let bind = Function.prototype.call.bind(Function.prototype.bind);
bind(f, o)() //
### `Object 系统默认方法`
function Foo (){}
let obj = new Foo ();
Object.getPrototypeOf(obj) // Foo.prototype
//空对象原型
Object.getPrototypeOf({}) // Object.prototype
// Object.prototype 原型
Object.getPrototypeOf(Object.prototype) //null
// Foo
Object.getPrototypeOf(Foo) // Function.prototype
let now = {};
let pro = {name:"Owen"};
Object.setPrototypeOf(now,pro);
now.name //"Owen"
let obj = Object.create(null);
obj.toString()// Error //会继承第二个参数的属性和方法
let obj = Object.create({}, {
p1: {
value: 123,
enumerable: true,
configurable: true,
writable: true,
},
p2: {
value: 'Owen',
enumerable: true,
configurable: true,
writable: true,
}
}); // 等同于
let obj = Object.create({});
obj.p1 = 123;
obj.p2 = 'Owen'; //生成的对象会继承它的原型对象的构造函数。
function Foo() {}
let f = new Foo();
let b = Object.create(f); b.constructor === Foo // true
b instanceof Foo // true
function F(){}
let f = new F()
F.prototype.isPrototypeOf(f) //true
//不管可不可遍历都会返回出来
Object.getOwnPropertyNames(Date);//["length", "name", "prototype", "now", "parse", "UTC"]
//返回可遍历属性
Object.keys(Date)// []
Array.hasOwnProperty('length')//true
### 拷贝对象
function copyOwn (target,origin){
Object.getOwnPropertyNames(origin).forEach((key)=>{
let desc =Object.getOwnPropertyDescriptor(origin,key);
Object.defineProperty(target,origin,desc);
})
return target
}
function copy(origin){
let clone = Object.create (Object.getPrototypeOf(origin));
copyOwn(clone,origin)
return clone
}
//es8
const copyTwo = origin =>Object.create( Object.getPropertyOf(origin),Object.getOwnPropertyDescriptor(origin) );
JavaScript 对象继承 OOP (三)的更多相关文章
- 实现JavaScript中继承的三种方式
在JavaScript中,继承可以通过三种手法实现原型链继承 使用apply.call方法 对象实例间的继承. 一.原型链继承 在原型链继承方面,JavaScript与java.c#等语言类似 ...
- javascript类继承系列三(对象伪装)
原理:在子类的构造器上调用超类构造器(父类构造器中的this指向子类实例),js提供了apply()和call()函数,可以实现这种调用 function baseClass() { this.col ...
- 详解JavaScript对象继承方式
一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Parent 构造函数成为 Children 的方法,然 ...
- javascript实现继承的三种方式
一.原型链继承 function Parent(){} function Child(){} Child.prototype = new Parent(); 通过对象child的prototype属 ...
- JavaScript(JS)之Javascript对象DOM(三)
https://www.cnblogs.com/haiyan123/p/7598320.html 一.什么是HTML DOM HTML Document Object Model(文档对象模型) ...
- JavaScript对象继承方式
一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Parent 构造函数 成为 Children 的方法, ...
- 深入理解javascript对象系列第三篇——神秘的属性描述符
× 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...
- javascript对象继承的实现
现在有两个对象,需要实现Chinese类型对象对Person类型对象的继承. 这里分两部分,属性和方法. 属性可以直接用构造函数的方法实现继承,而方法则要通过原型链来实现继承. 先解释什么是原型链,每 ...
- Javascript 对象继承 原型链继承 对象冒充 call 混合方式
一.原型链继承 function ClassA() {} ClassA.prototype.color = "blue"; ClassA.prototype.sayColor = ...
随机推荐
- Error: connection reset by peer ,during filebeat connect to elk.
Error screenshot like below: Reason: What I found that was the machine failing had same configuratio ...
- 《图解HTTP》阅读笔记--第六章--HTTP首部
第六章.HTTP首部 <非常重要且恐怖的一章了> HTTP报文=报文首部+(CR+LF)+报文实体 首部字段:HTTP报文首部字段=(首部字段名:字段值)们---类型*4: 通用首部字段( ...
- 「产品经理全连接系列2」企业如何开展敏捷或DevOps的研发变革
大家好,我是华为云的产品经理 恒少: 作为布道师和产品经理,出差各地接触客户是常态,经常和华为云的客户交流.布道.技术沙龙,但是线下交流,覆盖的用户总还是少数. 我希望可以借线上的平台,和用户持续交流 ...
- 2019年GPLT L2-4 彩虹瓶 比赛题解 中国高校计算机大赛-团体程序设计天梯赛题解
彩虹瓶的制作过程(并不)是这样的:先把一大批空瓶铺放在装填场地上,然后按照一定的顺序将每种颜色的小球均匀撒到这批瓶子里. 假设彩虹瓶里要按顺序装 N 种颜色的小球(不妨将顺序就编号为 1 到 N).现 ...
- redhat7查看系统版本 修改主机名
在CentOS或RHEL中,有三种定义的主机名:静态的(static),瞬态的(transient),以及灵活的(pretty).“静态”主机名也称为内核主机名,是系统在启动时从 /etc/hostn ...
- 序列终结者 BZOJ 1251 Splay
题目背景 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术 ...
- 分页插件PageHelper
一.PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,SQLite,Hsqldb,Po ...
- C++_引用变量探究
什么是引用 引用变量是已定义变量的别名. 如何定义引用变量: int rats; int & rodents = rats; 其中&不失地址运算符,而是类型标识符的一部分.就行声明ch ...
- poj3274 找平衡数列(哈希加一点数学思维)
题目传送门 题目大意:有n只牛,每只牛有k个属性,接下来n个数字,每个数字的二进制位上的1和0分别表示某种属性的有或者无,然后一个特殊数列就是,一个区间内所有牛的各种属性的总和相等(有e种1属性 e ...
- 自定义Razor 标签
1.首先需要一个abstract class WebViewPage<T> ,继承系统的 System.Web.Mvc.WebViewPage<TModel> 再定义一个Web ...