'Javascript知识点整理'

常用算法

二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function binarySearch(target, arr) {
var start = 0;
var end = arr.length - 1;
while(end >= start) {
var mid = parseInt(start + (end - start) / 2);
if (target === arr[mid]) {
return mid;
} else if (target > arr[mid]) {
start = mid + 1;
} else {
end = mid -1;
}
}
return -1;
}

快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//快速排序
function quickSort(arr) {
if (arr.length <=1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [], right = [];
for(var i = 0, l = arr.length; i < l; i++) {
if (arr[i] <= pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat(pivot, quickSort(right));
}

归并排序

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
//归并排序
function mergeSort(arr) {
if (arr.length <= 1) {
return arr;
}
var mid = Math.floor(arr.length / 2);
var left = arr.slice(0, mid);
var right = arr.slice(mid);
var merge = function(left, right){
var result = [];
while(left.length > 0 && right.length > 0) {
if(left[0] < right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while(left.length > 0) {
result.push(left.shift());
}
while(right.length > 0) {
result.push(right.shift());
}
return result;
}
return merge(mergeSort(left), mergeSort(right));
}

数组扁平化

1
2
3
4
5
6
7
8
function arrFlatten(arr) {
return arr.reduce(function(accumulator, currenValue, currentIndex, arr){
if(Array.isArray(currenValue)) {
return accumulator.concat(arrFlatten(currenValue))
}
return accumulator.concat(currenValue);
}, [])
}

函数节流和防抖

防抖的原理就是:你尽管触发事件,但是我一定在事件触发 n 秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,那我就以新的事件的时间为准,n 秒后才执行,总之,就是要等你触发完事件 n 秒内不再触发事件,我才执行。

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
//函数防抖
function debounce(fn, delay, immediate) {
// immediate 参数判断是否是立刻执行
var timer = null, result;
var debounced = function() {
var context = this, //this指向dom元素
args = arguments; //传递event对象
if(timer)clearTimeout(timer);
if(immediate) {
// 如果已经执行过,不再执行
var callNow = !timer;
timer = setTimeout(function() {
timer = null;
}, delay)
if(callNow) result = fn.apply(context, args);
} else {
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
return result;
}
debounced.cancel = function() {
clearTimeout(timer);
timer = null;
}
return debounced;
}

节流的原理很简单:

如果你持续触发事件,每隔一段时间,只执行一次事件。

根据首次是否执行以及结束后是否执行,效果有所不同,实现的方式也有所不同。我们用leading代表首次是否执行,trailing代表结束后是否再执行一次。

关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。
1.时间戳:马上执行,delay时间后不执行

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(fn, delay) {
var context, args;
var last = 0;
return function() {
context = this;
args = arguments;
var now = +new Date();
if (now - last > delay) {
fn.apply(context, arguments);
last = now;
}
}
}

2.定时器: delay时间后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function throttle(fn, delay) {
var context, args;
var timer = null;
return function() {
context = this;
args = arguments;
if (!timer) {
timer = setTimeout(function() {
timer = null;
fn.apply(context, args);
}, delay)
}
}
}

有头有尾

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
function throttle(fn, delay) {
var context, args;
var timer = null;
var last = 0;
var later = function() {
last = +new Date();
timer = null;
fn.apply(context, args);
}
return function() {
context = this;
args = arguments;
var now = +new Date();
var remaining = delay - (now - last);
if (remaining <= 0 || remaining > delay) {
if(timer) {
clearTimeout(timer);
timer = null;
}
fn.apply(context, args);
last = now;
} else if(!timer){
timer = setTimeout(later, remaining)
}
}
}

实现有头无尾或者无头有尾
leading:false 表示禁用第一次执行
trailing: false 表示禁用停止触发的回调

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
function throttle(fn, delay, options) {
var context, args, timer = null, last = 0;
if (!options) options = {};
var later = function() {
last = options.leading === false? 0 : new Date().getTime();
timer = null;
fn.apply(context, args);
}
var throttled = function() {
context = this;
args = arguments;
var now = +new Date();
if(!last && options.leading === false) last = now;
var remaining = delay - (now - last);
if (remaining <= 0 || remaining > delay) {
if (timer) {
clearTimeout(timer);
timer = null;
}
fn.apply(context, args);
last = now;
} else if(!timer && options.trailing !== false) {
timer = setTimeout(later, remaining);
}
}
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
}
return throttled;
}

判断是否为数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//判断是否是数字
function isNumber(num) {
var number = +num;
if ((number - number) !== 0) {
// Discard Infinity and NaN
return false;
}
if (number === num) {
return true;
}
if (typeof num === 'string') {
// String parsed, both a non-empty whitespace string and an empty string
// will have been coerced to 0. If 0 trim the string and see if its empty.
if (number === 0 && num.trim() === '') {
return false;
}
return true;
}
return false;
}

事件中心

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
//Event
function Event() {
this._cache = {};
}
Event.prototype.on = function(type, callback) {
var fns = (this._cache[type] = this._cache[type] || []);
if (fns.indexOf(callback) === -1) {
fns.push(callback);
}
return this;
}
Event.prototype.trigger = function(type, data) {
var fns = this._cache[type];
if (Array.isArray(fns)) {
fns.forEach(fn => {
fn(data);
})
}
return this;
}
Event.prototype.off = function(type, callback) {
var fns = this._cache[type];
if (Array.isArray(fns)) {
if (Array.isArray(fns)) {
if(callback) {
var index = fns.indexOf(callback);
if (index !== -1) {
fns.splice(index, 1);
}
} else {
fns.length = 0;
}
}
}
return this;
}

Lazyman的实现

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
60
61
//LazyMan
function _LazyMan(name) {
var self = this;
this.stack = [];
var fn = (function(n) {
var name = n;
return function() {
console.log('Hi, this is ' + name);
self.next();
}
})(name);
this.stack.push(fn);
setTimeout(function() {
self.next();
})
}
_LazyMan.prototype.next = function() {
var fn = this.stack.shift();
fn && fn();
}
_LazyMan.prototype.eat = function(name) {
var self = this;
var fn = (function(name) {
return function(){
console.log('eat ' + name);
self.next();
}
})(name)
this.stack.push(fn);
return this;
}
_LazyMan.prototype.sleep = function(time) {
var self = this;
var fn = (function(time) {
return function() {
setTimeout(function() {
console.log("Wake up after " + time + "s!");
self.next();
}, time * 1000)
}
})(time)
this.stack.push(fn);
return this;
}
_LazyMan.prototype.sleepFirst = function(time) {
var self = this;
var fn = (function(time) {
return function() {
setTimeout(function() {
console.log("Wake up after " + time + "s!");
self.next();
}, time * 1000)
}
})(time)
this.stack.unshift(fn);
return this;
}
function LazyMan(name) {
return new _LazyMan(name);
}

HTML5拖拽实现

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
//HTML5拖拽
var eleDrags = $('.draglist'),
lDrags = eleDrags.length,
eleDrag = null;
for (var i = 0; i < lDrags; i++) {
eleDrags[i].onselectstart = function() {
return false;
}
eleDrags[i].ondragstart = function(ev) {
ev.dataTransfer.effactAllow = 'move';
ev.dataTransfer.setData('text',ev.target.innerHTMl);
ev.dataTransfer.setDragImage(ev.target, 0, 0);
eleDrag = ev.target;
return true;
}
eleDrags[i].ondragend = function(ev) {
ev.dataTransfer.clearData('text');
eleDrag = null;
return false;
}
eleDrags[i].ondragover = function(ev) {
ev.preventDefault = true;
return false;
}
eleDrags[i].ondragenter = function(ev) {
this.style.color = "#fff";
return true;
}
eleDrags[i].ondragleave = function(ev) {
this.style.color = "#000";
return true;
}
eleDrags[i].ondrop = function(ev, divdom) {
var that = this;
if(eleDrag) {
var temp = eleDrag.innerHTML;
eleDrag.innerHTML = that.innerHTML;
that.innerHTML = temp;
}
return false;
}
}

原生ajax的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//原生ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readystate === 4) {
if (chr.status === 200) {
console.log(xhr.responseTetx);
} else {
console.log("Error:" + chr.status);
}
}
}
xhr.open('GET', 'xxxx');
xhr.header('Content-Type','application/json');
xhr.send();

Promise模拟实现

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
//promise实现
function promise(fn) {
let self = this;
this.value = '';
this.error = '';
this.status = 'pending';
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];
function resolve(value) {
if (slef.status === 'pending') {
self.status = 'resolved';
slef.value = value;
setTimeout(() =>{
self.onResolveCallbacks.forEach((callback) => {
callback.(slef.value);
})
}, 0)
}
}
function reject(error) {
if (slef.status === 'pending') {
self.status = 'rejected';
slef.error = error;
setTimeout(() =>{
self.onRejectCallbacks.forEach((callback) => {
callback.(slef.error);
})
}, 0)
}
}
fn(resolve, reject);
}
promise.prototype.then = function(onFulFilled, onRejected) {
if (this.status === 'pending'){
this.onResolveCallbacks.push(onFulFilled);
this.onRejectCallbacks.push(onRejected);
} else if(this.status === 'resolved') {
onFulFilled(this.value);
} else {
onRejected(this.error);
}
return this;
}

call和apply的模拟实现

call()方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法。

1
2
3
4
5
6
7
8
9
10
11
Function.prototype.call = Function.prototype.call || function(context) {
var context = context || window;
context.fn = this;
var arr = [];
for (var i = 1, l = arguments.length; i< l; i++) {
arr.push('arguments['+ i +']');
}
var result = eval('context.fn('+ arr +')');
delete context.fn;
return result;
}

apply功能与call一致,函数产地的参数是数组形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Function.prototype.apply = Function.prototype.apply || function(context, arr) {
var context = context || window;
context.fn = this;
if (!arr) {
context.fn();
} else {
var args = [];
for(var i = 0, l = arr.length; i < l;i++) {
args.push('arr[+ i +]');
}
var result = eval('context.fn('+ args +')');
}
delete context.fn();
return result;
}

bind的模拟实现

bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Function.prototype.bind = Function.prototype.bind || function(context) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function() {};
var fBound = function() {
// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值
// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
self.apply(this instanceof fBound? this : context, args.concat(Array.prototype.slice.call(arguments)));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}

new的模拟实现

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一

1
2
3
4
5
6
7
function objectFactory() {
var obj = {};
var constructor = Array.prototype.shift.call(arguments);
obj.__proto__ = constructor.prototype;
var result = constructor.apply(obj, arguments);
return typeof result === 'object' : result : obj;
}

数组去重

双层循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function unique(array) {
var result = [];
for (var i = 0, arrLength = array.length; i < arrLength; i++) {
for(var j = 0, resLength = result.length; j < resLength; j++) {
if (array[i] === result[j]) {
break;
}
}
if (j === resLength) {
result.push(array[i])
}
}
return result;
}

indexOf

1
2
3
4
5
6
7
8
9
function unique(array) {
var result = [];
for (var i = 0, arrLength = array.length; i < arrLength; i++) {
if (result.indexOf(array[i]) === -1) {
result.push(array[i])
}
}
return result;
}

排序后去重

1
2
3
4
5
6
7
8
9
10
11
12
function unique(array) {
var result = [];
var sortedArray = array.concat().sort();
var seen;
for(var i = 0, len = sortedArray.length; i < len; i++) {
if (!i || seen !== sortedArray[i]) {
result.push(sortedArray[i]);
}
seen = sortedArray[i];
}
return result;
}

unique API

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
// isSorted:是否排序 iteratee:迭代函数
function unique(array, isSorted, iteratee) {
var result = [];
var seen = [];
for(var i = 0, len = array.length; i < len; i++) {
var value = array[i];
var computed = iteratee? iteratee(value, index, array) : value;
if (isSorted) {
if (!i || seen !== computed) {
result.push(value);
}
seen = computed;
} else if(iteratee) {
if (seen.indexOf(computed) === -1) {
seen.push(computed);
result.push(value);
}
} else {
if(result.indexOf(value) === -1) {
result.push(value);
}
}
}
return result;
}

Array.filter

1
2
3
4
5
function unique(array) {
return array.filter((value, index) => {
return array.indexOf(value) === index;
})
}

Object键值对

1
2
3
4
5
6
function unique(array) {
var obj = {};
return array.filter((value, index) => {
return obj.hasOwnProperty(typeof value + JSON.stringify(value))? false : (obj[typeof value + JSON.stringify(value)] = true)
})
}

ES6

1
2
3
4
5
6
7
8
9
//Set
function unique(array) {
return Array.from(new Set(array));
}
//Map
function unique(array) {
var seen = new Map();
return array.filter((value) => !seen.has(value) && seen.set(value, 1));
}
1
var array = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];
方法 结果 说明
for循环 [1, “1”, null, undefined, String, String, /a/, /a/, NaN, NaN] 对象和 NaN 不去重
indexOf [1, “1”, null, undefined, String, String, /a/, /a/, NaN, NaN] 对象和 NaN 不去重
排序去重 [/a/, /a/, 1, “1”, String, String, NaN, NaN, null, undefined] 对象和 NaN 不去重
filter + indexOf [1, “1”, null, undefined, String, String, /a/, /a/] 对象不去重 NaN 会被忽略掉
优化后的键值对方法 [1, “1”, null, undefined, String, /a/, NaN] 全部去重
Set、Map [1, “1”, null, undefined, String, String, /a/, /a/, NaN] 对象不去重 NaN去重

类型判断

1
2
3
4
5
6
7
8
9
10
function type(obj) {
var class2type = {};
"Boolean Number String Function Array RegExp Object Error Date".split(' ').map((item) => {
return class2type['[object ' + item +']'] = item.toLowerCase();
})
if (obj == null) {
return obj + '';
}
return typeof obj === 'object' || typeof obj === 'function'? class2type[Object.prototype.toString.call(obj)] || 'object' : typeof obj;
}

EmptyObject

1
2
3
4
5
6
7
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}

Window对象

1
2
3
function isWindow(obj) {
return obj !== null && obj === obj.window;
}

isArrayLike

1
2
3
4
5
6
7
8
function isArrayLike(obj) {
var length = !!obj && "length" in obj && obj.length;
var resType = type(obj);
if (resType === 'function' || isWindow(obj)) {
return false;
}
return resType === 'array' || length === 0 || type(length) === 'number' && length > 0 && (length - 1) in obj;
}

isElement

1
2
3
function isElement(obj) {
return !!(obj && obj.nodeType === 1);
}

深浅拷贝

简单的数组深浅拷贝

1
concat(), slice(), Array.from(), [...spread], JSON.parse(JSON.stringify())

浅拷贝

1
2
3
4
5
6
7
8
9
10
function shallowCopy(obj) {
if(typeof obj !== 'object') return false;
var newObj = obj instanceof Array? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}

深拷贝

1
2
3
4
5
6
7
8
9
10
function deepCopy(obj) {
if(typeof obj !== 'object') return false;
var newObj = obj instanceof Array? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object'? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}

Jquery的extend

定义:合并两个或者更多的对象的内容到第一个对象中

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
function extend() {
var deep = false;
var name, options, copy;
var length = arguments.length;
var target = arguments[0] || {};
var i = 1;
if (typeof target === 'boolean') {
deep = target;
target = arguments[i] || {};
i++
}
// 如果target不是对象,我们无法进行复制的所以设为{}
if (typeof target !== 'object') {
target = {}
}
for(; i < length; i++) {
options = arguments[i];
if (options !== null) {
for(name in options) {
copy = options[name];
if(deep && copy && typeof copy === 'object') {
target[name] = extend(true, target[name], options[name])
} else if(copy !== undefined){
target[name] = copy;
}
}
}
}
return target;
}

求数组的最大值和最小值

reduce

1
2
3
4
5
function max(arr) {
return arr.reduce((prev, current) => {
return Math.max(prev, current);
})
}

apply

1
2
3
function max(arr) {
return Math.max.apply(null, arr);
}

ES6

1
2
3
function max(arr) {
return Math.max(...arr);
}

Flatten

reduce

1
2
3
4
5
function flatten(arr) {
return arr.reduce((prev, next) => {
return prev.concat(Array.isArray(next)? flatten(next) : next);
},[])
}

ES6 flat的模拟

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
/**
* 数组扁平化
* @param {Array} input 要处理的数组
* @param {Number} depth 指定嵌套数组中的结构深度
*/
function flatten(input, depth) {
var output = [];
if (depth === 0) {
return output.concat(input);
}
var depth = depth || 1;
var j = 1;
for (var i = 0, len = input.length; i < len; i++) {
var value = input[i];
if (Array.isArray(value)) {
if (depth === Infinity) {
output = output.concat(flatten(value, depth - 1));
} else if (j <= depth) {
output = output.concat(flatten(value, depth - 1))
} else {
output.push(value);
}
}
else {
output.push(value);
}
}
return output;
}

数组中查找指定元素

findIndex

1
2
3
4
5
6
function findIndex(array, predicate, context) {
for (var i = 0, len = array.length; i < len; i++) {
if (predicate.call(context, array[i], i, array)) return i;
}
return -1;
}

findLastIndex

1
2
3
4
5
6
function findLastIndex(array, predicate, context) {
for (var i = array.length - 1; i >= 0; i--) {
if (predicate.call(context, array[i], i, array)) return i;
}
return -1;
}

createIndexFinder

1
2
3
4
5
6
7
8
9
10
function createIndexFinder(dir) {
return function(array, predicate, context) {
var length = array.length;
var i = dir > 0? 0 : length - 1;
for (; i >= 0 && i < length; i += dir) {
if (predicate.call(context, array[i], i, array)) return i;
}
return -1;
}
}

sortedIndex

在一个排好序的数组中找到value对应的位置,保证插入数组后,依然保持有序的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function sortedIndex(array, obj, iteratee, context) {
var cb = function(func, context) {
if (context === void 0) return func;
return function() {
return func.apply(context, arguments);
}
}
iteratee = cb(iteratee, context);
var low = 0, high = array.length;
while(high > low) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < iteratee(obj)) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return mid;
}

createIndexOfFinder

indexOf 方法也可以多传递一个参数 fromIndex,从 MDN 中看到 fromIndex 的讲究可有点多:

设定开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回 -1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即 -1 表示从最后一个元素开始查找,-2 表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,仍然从前向后查询数组。如果抵消后的索引值仍小于 0,则整个数组都将会被查询。其默认值为 0。

lastIndexOf 的 fromIndex:

从此位置开始逆向查找。默认为数组的长度减1,即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function createIndexOfFinder(dir) {
return function(array, item, idx) {
var i = dir > 0? 0 : array.length - 1;
length = array.length;
if (typeof idx === 'number') {
if (dir > 0) {
i = idx >=0 ? idx : Math.max(idx + length, 0)
} else {
i = idx >=0 ? Math.min(idx, length - 1) : idx + length;
}
}
for(; i >= 0 && i < length; i += dir) {
if (array[i] === item) return i;
}
return -1;
}
}

ES5实现ES6的class

es6的代码:

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
class Parent {
constructor(name) {
this.name = name;
}
sayHello() {
return 'Hello, i am ' + this.name;
}
static onlySayHello() {
return 'Hello';
}
get name() {
return 'kevin';
}
set name(newName) {
console.log('my name is ' + newName);
}
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
var child1 = new Child('kevin', 18);

es5实现

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
'use strict'
//静态方法定义在实例对象上,方法定义在实例的原型对象上
var _createClass = function() {
function defineProperties(target, props) {
for(var i = 0, len = props.length; i < len; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
}
}()
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised-super() hasn't been called")
}
return call && (typeof call === 'object' || typeof call === 'function')? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new ReferenceError("Super expression msut either be a function or null, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true }});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
//class只能通过new构造函数使用
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function')
}
}
var Parent = function() {
function Parent(name) {
_classCallCheck(this, Parent);
this.name = name;
}
_createClass(Parent, [{
key: 'sayHello',
value: function sayHello() {
return 'Hello, I am ' + this.name;
}
}, {
key: 'get',
value: function get() {
return 'kevin';
}
}, {
key: 'set',
value: function set(nemName) {
console.log('my name is ' + newName);
}
}], [{
key: 'onlySayHello',
value: function onlySayHello() {
return 'Hello';
}
}])
return Parent;
}();
var Child = function(_Parent) {
_inherits(Child, _Parent);
function Child(name, age) {
_classCallCheck(this, Child);
var _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name))
_this.age = age;
return _this;
}
return Child;
}(Parent)
var child1 = new Child('kevin', 18);