/*
* 类型检测
**
var arr = []
console.log(typeof arr )
var x = typeof x
var res = typeof typeof x
console.log(x, res) // undefined string
console.log([typeof null, null instanceof Object])
console.log(typeof typeof 0)
var arr = []
console.log(typeof arr, Object.prototype.toString.call(arr))
console.log(Object.prototype.toString.call(undefined))
*/
/*
* 类型转换
**
console.log("2" + 3 + 4)
console.log('5' + 3, 5 + '3')
var a = parseInt('111办公室')
console.log(a)
var newArr = ['0x1', '0x2', '0x3'].map(val => parseInt(val))
console.log(newArr)
console.log(1 + '1')
console.log(parseInt('77', 40))
console.log(parseInt('77', 10))
console.log(parseInt('77', 2))
console.log(parseInt('77', 8))
console.log(parseInt('77', 16))
console.log(parseInt('77', 5))
*/
/*
* 逻辑判断
**
console.log([5<6<3, 3<2<4])
console.log((2<3) || (3 < 2))
// 逻辑或和逻辑与 都是短路逻辑,如果左侧表达式为 true,则直接短路返回结果,不再运算右侧表达式
console.log(true || false && false, true && false || true)
*/
/**
* 其他
**
console.log(1 + - + + + - + 1)
console.log(['a',,'b',,].length)
*/
/*
* js 基础
**
function showCase(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B':
console.log('Case B');
break;
case undefined:
console.log('Case undefined');
break;
default:
console.log('Case default');
}
}
showCase(new String('A')); // -> 'Case default'
showCase(String('A')); // -> 'Case A'
function funcA(x){
var temp = 4;
function funcB(y){
console.log( ++x + y + (temp--));
}
funcB(5);
}
funcA(6)
var varArr = function(i,j,str) {
console.log('j val is ', j)
return j == 0 ? str : varArr(i,--j,(str+= " " + i[j]));
}
var arr = new Array('apple','orange','peach','lime');
var str = varArr(arr,arr.length,"");
console.log(str);
// var i = ['apple', 'orange', 'peach', 'lime'], j = 4, // -> j = 3 str = 'lime'
// i = ['apple', 'orange', 'peach', 'lime'], j = 3, // -> j = 2 str = 'lime peach'
// i = ['apple', 'orange', 'peach', 'lime'], j = 2, // -> j = 1 str = 'lime peach orange'
// i = ['apple', 'orange', 'peach', 'lime'], j = 1, // -> j = 0 str = 'lime peach orange apple'
// i = ['apple', 'orange', 'peach', 'lime'], j = 0, str = 'lime peach orange apple'
function greetingMaker(greeting) {
function addName(name) {
greeting = greeting.split(' ').reverse().join("-");
return greeting + " " + name;
}
return addName;
}
var daytimeGreeting = greetingMaker("Good Day to you");
console.log(daytimeGreeting('shasha'));
String.prototype.GetNum = function() {
var regEx = /[^\d]/g;
return this.replace(regEx, '');
};
var str = "a1b2c3";
str = str.GetNum();
console.log(str);
function sum(a, b) {
return a + b;
}
var res = sum(1, "2");
console.log(res)
var str = "我非常喜欢编程";
str.length = 3;
console.log(str, str.length); // -> '我非常喜欢编程' 7
var arr = ['apple', 'orange', 'peach', 'lime']
arr.length = 2
console.log(arr) // -> ['apple', 'orange']
var number = 0;
console.log(number++); // -> 0
console.log(++number); // -> 2
console.log(number); // -> 2
function nums(a, b) {
if (a > b)
console.log('a is bigger')
else
console.log('b is bigger')
return a + b
}
console.log(nums(4, 2))
console.log(nums(1, 2))
function side(arr) {
arr[0] = arr[2];
}
function func1(a, b, c = 3) {
c = 10;
side(arguments);
console.log('func1', arguments)
console.log(a + b + c);
}
function func2(a, b, c) {
c = 10;
side(arguments);
console.log('func2', arguments)
console.log(a + b + c);
}
// 形参、实参 和 arguments 的关系:
// 形参:声明函数时所有参数,称为形参。
// 实参:调用函数时传递的所有参数,称为实参
// arguments 是包含所有 实参 的类数组对象。arguments 对象的值 会自动同步 到对应的形参,当函数给默认值的时候,arguments 与形参的映射关系不存在
// 需注意的地方: 首先 arguments 对象的 长度由实参决定; 相对应的arguments 与 形参才会建立映射关系;
func1(1, 1, 1);
func2(1, 1, 1);
var a = 3;
var b = new Number(3);
var c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
var a = [];
a.push(1, 2);
a.shift(3, 4); // shift 删除数组的第一项,该方法不需要传递参数,有参数会忽略参数
a.concat([5, 6]); // concat 不会改变原数组,会返回一个新数组,需要变量接收
a.splice(0, 1, 2); // 将第0项删除,并替换为2
console.log(a)
var a = {}, b = '123', c = 123;
a[b] = 'b'; // -> a['123'] = 'b'
a[c] = 'c'; // c变量的值作为对象的键名时,自动转换为string类型,此行执行后会相当于将上一行的重新赋值 a['123'] = 'c'
console.log(a, a[b]); // 'c'
// example 2
var a = {}, b = Symbol('123'), c = Symbol('123');
a[b] = 'b';
a[c] = 'c'; // b和c是两个不同的symbol变量值,所以a对象有两个属性
console.log(a, a[b]);
// example 3
var a = {}, b = {key:'123'}, c = {key:'456'};
a[b] = 'b'; // 对象类型的值作为对象的属性名时,调用对象的toString方法自动转换为string类型,值为"[object Object]",相当于a["[object Object]"] = 'b'
a[c] = 'c'; // 相当于a["[object Object]"] = 'c', 重置了上一行对a对象上"[object Object]"属性的值
console.log(a, a[b]);
console.log(null == undefined)
console.log(0.1 + 0.2 == 0.3) // 浮点数精确度的问题
console.log(typeof NaN) // -> 'number'
console.log(typeof Function)
console.log(typeof Object)
console.log(typeof {})
console.log('a' + 1) // -> 'a1'
console.log('a' - 1) // -> NaN
console.log(Function instanceof Object)
console.log(Object instanceof Function)
var array = []
for(var i = 0; i < 3; i++) {
array.push(() => i)
}
var newArray = array.map(el => el())
console.log(newArray) // -> [3,3,3]
var a = function (m, n) {
var b = function (l) {
return l <= m ? l * b(l + 1) : 1;
}
return b(m - n + 1);
}
console.log(a(4, 2));
// m = 4, n = 2, l = 3
// 3 * b(4)
// b(4) = 4 * b(5)
// b(5) = 1
// 3 * 4 * 1 = 12
console.log(typeof undefined == typeof NULL, typeof NULL) // -> true 'undefined'
console.log(typeof function() {} == typeof class {}, typeof class {}) // -> true 'function'
var a = 10
var b = {
age: 11
}
function fn(x,y) {
--y.age;
return --x;
}
// 函数之参数按值传递:参数如果是基本类型是按值传递,如果是引用类型按共享传递,而按共享传递是传递对象的引用的副本,但是因为拷贝副本也是一种值的拷贝,所以在高程中也直接认为是按值传递了
// 按值传递:也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样
fn(a,b)
console.log(a, b) // -> 10 { age: 10 }
var number = 4;
var numberFactorial = (function factorial (number){
return (number === 0)? 1: number* factorial(number-1)
})(number)
console.log(numberFactorial)
// 4 * func(3)
// func(3) = 3 * func(2)
// func(2) = 2 * func(1)
// func(1) = 1 * func(0)
// func(0) = 1
// 4*3*2*1 = 24
// 逻辑或和逻辑与 都是短路逻辑,如果左侧表达式为 true,则直接短路返回结果,不再运算右侧表达式
const first = () => { console.log('first'); return false; }
const second = () => { console.log('second'); return true; }
console.log(first() && second() ); // -> 'first' false --> sencond 未执行
console.log( second() || first() ); // -> 'second' true --> first 未执行
var arr=[1,2,3];
arr.push(arr.shift())
console.log(arr[1],arr[2])
*/
/*
* this问题
**
var x = 1;
var obj = {
x: 3,
fun:function () {
var x = 5;
return this.x;
}
};
var fun = obj.fun;
console.log(obj.fun(), fun()); // -> 3 1
var a = 5;
function test() {
a = 0;
console.log(a);
console.log(this.a, this);
var a;
console.log(a);
}
// new 运算符的实现机制:
// 1.创建一个新的空对象
// 2.设置原型,将对象的原型设置为函数的prototype对象
// 3.让函数的this指向这个对象,指向函数的代码(为这个新对象添加属性)
// 4.判断函数的返回值类型,如果是值类型,返回创建的对象;如果是引用类型,就返回这个引用类型的对象
new test(); // -> 0 undefined {} 0
// 这道题考察的是箭头函数中没有this的这个特性
function fun () {
return () => {
return () => {
return () => {
console.log(this.name)
}
}
}
}
var f = fun.call({name: 'foo'}) // 将fun函数里的this绑定为{name: 'foo'},
// fun() 执行返回的f函数是箭头函数, 箭头函数里没有this,不能通过call、apply、bind改变this执行,
// 箭头函数内的this需要向上层作用域查找, -> fun的作用域中的this
var t1 = f.call({name: 'bar'})()()
var t2 = f().call({name: 'baz'})()
var t3 = f()().call({name: 'qux'})
const Person = (name="wang",age=10) => {
this.name = name;
this.age = age;
return this.name +' is '+ this.age + 'years old'
}
console.log(Person.prototype)
// tip: 箭头函数内没有this, new.target, 没有原型对象 不能使用new 关键字
// let result = new Person('zhang',11)
// console.log(result)
var name = 'global';
var obj = {
name: 'local',
foo: function(){
this.name = 'foo';
}.bind(window)
};
var bar = new obj.foo();
setTimeout(function() {
console.log(window.name);
}, 0);
console.log(bar.name);
var bar3 = bar2 = bar;
bar2.name = 'foo2';
console.log(bar3.name);
var obj = {
name:"zhangsan",
sayName:function(){
console.log(this.name);
}
}
var wfunc = obj.sayName;
obj.sayName();
wfunc(); // -> '' Tips: name属性比较特殊 默认情况下 window.name = ''
var name = "lisi"; // window.name = 'lisi'
obj.sayName();
wfunc();
*/
/* 事件循环
**
const promiseA = Promise.resolve('a')
promiseA.then((res) => {
console.log('promiseA1', res)
}).then((res) => {
console.log('promiseA2', res)
})
const promiseB = Promise.resolve('b')
promiseB.then((res) => {
console.log('promiseB1', res)
})
promiseB.then((res) => {
console.log('promiseB2', res)
})
// -> promiseA1 promiseB1 promiseB2 promiseA2
setTimeout(() => {
console.log(1)
}, 0)
const P = new Promise((resolve, reject) => {
console.log(2)
setTimeout(() => {
resolve()
console.log(3)
}, 0)
})
P.then(() => {
console.log(4)
})
console.log(5)
setTimeout(function(){
console.log(1);
}, 0)
new Promise(function(resolve){
console.log(2);
resolve();
console.log(3);
}).then(function(){
console.log(4);
})
console.log(5);
(async () => {
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
// await 后面的Promise没有执行resolve/reject回调函数,状态不会发生改变即一直是pending状态,所以then函数里不会执行,
// 而且await会阻塞后面代码的执行,所以5也不会输出
await new Promise((resolve, reject) => {
console.log(3);
}).then(() => {
console.log(4);
});
console.log(5);
})();
new Promise((resolve) => {
console.log('1')
resolve()
console.log('2')
}).then(() => {
console.log('3')
})
setTimeout(() => {
console.log('4')
})
console.log('5')
var p1 = new Promise(function(resolve, reject){
resolve("2")
})
setTimeout(function(){
console.log("1")
},10)
p1.then(function(value){
console.log(value)
})
setTimeout(function(){
console.log("3")
},0)
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise2');
});
setTimeout(function() {
console.log(1)
},0)
new Promise(function executor(resolve){
console.log(2)
for (var i = 0; i<10000; i++) {
i - 9999 && resolve()
}
console.log(3)
}).then(function() {
console.log(4)
})
console.log(5)
*/
/**
* 原型和原型链
var Foo = (function() {
var x = 0;
function Foo() {}
Foo.prototype.increment = function() {
++x;
console.log(x);
};
return Foo;
})();
var a = new Foo();
a.increment(); // -> 1
a.increment(); // -> 2
var b = new Foo();
a.increment(); // -> 3
var name = 'Jay'
function Person(name){
this.name = name;
console.log(this.name)
}
var a = Person('Tom') // -> 'Tom'. 当普通函数调用,全局环境下this指向window,函数体内没有return语句则函数调用后返回值为undefined
console.log(name) // -> 'Tom'
console.log(a) // -> undefined
var b = new Person('Michael') // -> 'Michael' 作为构造函数调用
console.log(b) // { name: 'Michael'}
// es6 -- class 类 和 类的继承
class A{}
class B extends A{}
const a = new A()
const b = new B()
console.log(a.__proto__ === A.prototype)
console.log(b.__proto__ === B.prototype)
console.log(B.__proto__ === A)
console.log(B.prototype.__proto__ === A.prototype)
console.log(b.__proto__.__proto__ === B.prototype.__proto__)
function test() {
getName = function() {
Promise.resolve().then(() => console.log(0));
console.log(1);
};
return this;
}
test.getName = function() {
setTimeout(() => console.log(2), 0);
console.log(3);
};
test.prototype.getName = function() {
console.log(4);
};
// 预解释阶段:变量提升和函数提升 执行阶段: 对getName变量赋值操作,覆盖了函数声明
var getName = function() {
console.log(5);
};
function getName() {
console.log(6);
}
test.getName();
getName();
test().getName(); // 执行test()时,函数体中的this是window,所以相当于重新为全局的getName函数赋值了, return this语句指定了test函数的返回值为window对象,所以可以直接链式调用getName方法
getName(); // 上一行对getName函数重新赋值了,调用最新赋值的函数体执行
new test.getName(); // 将test对象上的getName函数作为构造函数,用new运算符执行
new test().getName(); // new test() 返回一个空对象,执行test原型对象上的getName方法
new new test().getName(); // new test()返回一个空对象 读取test原型对象上的getName方法作为构造函数,用new运算符执行
// test.getName() -> 3 宏任务1 console.log(2)
// getName() -> 5
// test().getName() -> 1 微任务1 console.log(0)
// getName() -> 1 微任务2 console.log(0)
// new test.getName() // -> 3 宏任务2 console.log(2)
// new test().getName() // -> 4
// new new test().getName() // -> 4
// 3 5 1 1 3 1 1 4 4 0 0 2 2
const Book = {
price: 32
}
const book = Object.create(Book); // 以Book为原型对象创建book对象,Book上的属性和方法都在book的原型上了
book.type = 'Math'; // 添加私有属性
delete book.price; // 删除私有属性,不影响原型对象上的属性
delete book.type; // 删除私有属性
console.log(book.price); // -> 32
console.log(book.type); // -> undefined
*/
/**
* 作用域和预编译
**
function sayHello() {
console.log(name); // -> undefined
console.log(age); // Uncaught ReferenceError: Cannot access 'age' before initialization
var name = "Tom";
let age = 18;
}
sayHello();
var foo = "Hello";
(function(){
var bar = " World";
console.log(foo + bar); // -> 'Hello World'
})();
console.log(foo + bar); // -> Uncaught ReferenceError: bar is not defined
var a = 10;
(function () {
console.log(a) // -> undefined
a = 5
console.log(window.a) // -> 10
var a = 20;
console.log(a) // -> 20
})()
"use strict"
var name = 'Jay'
var person = {
name: 'Wang',
pro: {
name: 'Michael',
getName: function () {
return this.name
}
}
}
console.log(person.pro.getName()) // -> 'Michael'
// 严格模式下 全局对象不再指向window,而是undefined
var people = person.pro.getName
console.log(people()) // -> Uncaught TypeError: Cannot read properties of undefined (reading 'name')
*/
/*
** ES6
// ES6 - 对象
const student = {name: 'ZhangSan'}
Object.defineProperty(student, 'age', {value: 22})
console.log(student)
console.log(Object.keys(student))
// ES6 - generator
function * cb(x, y) {
for(let i = Math.ceil(x); i <= y; i++) {
yield i;
}
}
var a = cb(6, 9);
console.log(a.next());
console.log(a.next());
// ES6 - 运算符之rest运算符
function fn(...args) {
console.log(typeof args);
}
fn(21); // -> 'object'
// ES6 - promise
Promise.reject(0)
.catch(e => e)
.catch(e => console.log(e))
// ES6 - class
class Person {
constructor (name) {
this.name = name;
}
greet () {
console.log(`Hi, my name is ${this.name}`);
}
greetDelay (time) {
setTimeout(() => {
console.log(`Hi, my name is ${this.name}`);
}, time);
}
}
// ES6 的 class 编译后所生成的ES5代码
function Person(name) {
this.name = name
}
Person.prototype.greet = function() {
console.log(`Hi, my name is ${this.name}`);
}
Person.prototype.greetDelay = function(time) {
setTimeout(() => {
console.log(`Hi, my name is ${this.name}`);
}, time);
}
// es6 - 标签模板
function getPersonInfo (one, two, three) {
console.log(one) // -> ["", " is ", " years old"]
console.log(two) // -> 'Lydia'
console.log(three) // -> 21
}
const person = 'Lydia'
const age = 21
getPersonInfo `${person} is ${age} years old`
// ES6 - module
// module.js
export default () => "Hello world"
export const name = "nowcoder"
export const person = {
name: "nowcoder",
age: 18
}
// index.js
import * as data from "./module"
console.log(data) // -> { default: () => "Hello world", name: "nowcoder", person: { name: "nowcoder",
age: 18 }
}
data.person.age = 24
// other.js
import * as data from "./module"
console.log(data.person) // { name: "nowcoder", age: 24 }
*/
// url上获取查询参数
function getUrlParam(sUrl, sKey) {
const startIndex = sUrl.indexOf('?') + 1
const endIndex = sUrl.indexOf('#')
let paramsStr = sUrl.slice(startIndex, endIndex)
if (!paramsStr) return ''
let params = paramsStr.split('&')
let obj = {}
params.forEach((item) => {
const [key, val] = item.split('=')
obj[key] = obj[key] ? obj[key].concat(val) : [val]
})
if (sKey) {
return obj[sKey] || ''
}
return obj
}
var res = getUrlParam('http:xxx?key=1&key=2&key=3&test1=4#hashkey', 'test1')
// console.log(res)
// 节流:滚动加载
function throttle(fn,delay) {
var lastTime = 0;
return function() {
var nowTime = Date.now()
if (nowTime - lastTime >= delay) {
fn.apply(this, arguments)
lastTime = nowTime
}
}
}
function createObject() {
let constructor = Array.prototype.shift.call(arguments)
if (typeof constructor !== 'function') {
throw new Error('type error')
}
let newObj = Object.create(constructor.prototype)
let result = constructor.apply(newObj, arguments)
let flag = result && (typeof result === 'object' || typeof result === 'function')
return flag ? result : newObj
}
function promiseAll(promises) {
return new Promise(function(resolve, reject) {
if (!Array.isArray(promises)) {
throw new TypeError('argument must be a array')
}
let resolvedCounter = 0
let promiseNum = promises.length
let resolveResult = []
for(let i = 0; i < promiseNum; i++) {
Promise.resolve(promises[i]).then((res) => {
resolvedCounter++
resolveResult[i] = res
if (resolvedCounter === promiseNum) {
return resolve(resolveResult)
}
}, error => {
return reject(error)
})
}
})
}
let p1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(1)
}, 1000)
})
let p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(2)
}, 2000)
})
let p3 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(3)
}, 3000)
})
// promiseAll([p3, p1, p2]).then(res => {
// console.log(res) // [3, 1, 2]
// })
Promise.race = function(promises) {
return new Promise(function(resolve, reject) {
for(let i = 0, len = promises.length; i < len; i++) {
promises[i].then(resolve, reject)
}
})
}
let promise1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(1);
},2000)
});
let promise2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(2);
},1000)
});
let promise3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(3);
},3000)
});
// Promise.race([promise1,promise2,promise3]).then(res=>{
// console.log('success >>>', res); // success >>>,2
// },rej=>{
// console.log('error >>>>', rej)
// })
let promise4 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(1);
},1000)
});
let promise5 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(2);
},1000)
});
let promise6 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(3);
},3000)
});
// Promise.race([promise3,promise4,promise5]).then(res=>{
// console.log('success', res);
// },rej=>{
// console.log('error', rej) // -> error, 1
// })
Promise.finally = function(onDone) {
this.then(onDone, onDone)
}
Promise.resolve = function(value) {
if (value && value instanceof Promise) {
return value
} else if (value && typeof value === 'object' && typeof value.then === 'function') {
return new Promise(resolve => value.then(resolve))
} else if (value) {
return new Promise(resolve => resolve(value))
} else {
return new Promise(resolve => resolve())
}
}
Promise.finally = function(cb) {
return this.then(data => {
return Promise.resolve(cb()).then(() => data)
}, err => {
return Promise.resolve(cb()).then(() => { throw err })
})
}
// 防抖 - 避免用户的多次点击向后端发送多次请求
function debounce(fn, wait) {
let timer = null
return function() {
let context = this, arg = arguments
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(context, arg)
}, wait)
}
}
// 节流 - onscroll事件,每隔一段时间触发一次,降低事件调用的次数
function throttle(fn, delay) {
let lastTime = Date.now()
return function() {
let context = this, args = arguments, nowTime = Date.now()
if (nowTime - lastTime >= delay) {
lastTime = Date.now()
return fn.apply(context, args)
}
}
}
// 类型判断函数
function getType(value) {
if (value == null) {
return value + ''
}
if (typeof value === 'object') {
let valueClass = Object.prototype.toString.call(value),
type = valueClass.split(" ")[1].slice(0, -1)
return type.toLowerCase()
} else {
return typeof value
}
}
// console.log(getType([]))
// 手写Object.create()
function create(obj) {
function F() {}
F.prototype = obj
return new F()
}
// 手写instanceof 方法
function myInstanceof(left, right) {
let proto = Object.getPrototypeOf(left),
prototype = right.prototype
while(true) {
if (!proto) return false
if (proto === prototype) return true
proto = Object.getPrototypeOf(proto)
}
}
// 手写 new 操作符
function createObject(fn, ...arg) {
if (typeof fn !== 'function') {
throw new Error('fn is not a function')
}
var obj = Object.create({})
obj.__proto__ = fn.prototype
const result = fn.apply(obj, arg)
return result && (typeof result === 'object' || typeof result === 'function') ? result : obj
}
let mapData = new Map([
['foo', 1],
['bar', 2]
])
// console.log(mapData.size)
// console.log(mapData.has('foo'))
mapData.set('baz', 3)
// console.log(mapData.get('bar'))
mapData.delete('foo')
// console.log(mapData.has('foo'))
mapData.clear()
// console.log(mapData.size)
// console.log(mapData.get('bar'))
var obj = { a: 1}
mapData.set(obj, 4)
// console.log(mapData.has(obj), mapData.get(obj))
var null222 = null
mapData.set(null222, 5)
// console.log(mapData.has(null222), mapData.get(null222))
let mapData1 = new Map([
['foo', 1],
['bar', 2]
])
for(let key of mapData1.keys()) {
// console.log('mapData1 key', key)
}
for(let val of mapData1.values()) {
// console.log('mapData1 value', val)
}
for(let [key, val] of mapData1.entries()) {
// console.log('mapData1', key, val)
}
mapData1.forEach((val, key, map) => {
// console.log('mapData1', val, key)
})
// let arr = ['a', 'b', 'c']
// arr.forEach((item, index, a) => {
// console.log('array forEach', item, index, a)
// })
// 只接受对象作为键名( null 除外),不接受其他类型的值作为键名。
// 而且 WeakMap 的键名所指向的对象,不计入垃圾回收机制。
let weakMapData = new WeakMap()
weakMapData.set(obj, 4)
// console.log(weakMapData.has(obj), weakMapData.get(obj))
// weakMapData.set('obj', 4)
// console.log(weakMapData.has('obj'), weakMapData.get('obj'))
// weakMapData.set(null222, 5)
// console.log(weakMapData.has(null222), weakMapData.get(null222))
function Person(name) {
this.name = name
}
// 修改原型
Person.prototype.age = 18
var p = new Person('hello')
p.height = 180
for (let key in p) {
if (p.hasOwnProperty(key)) {
// 遍历实例自己的属性,不遍历原型上的属性方法
// console.log(key) // -> name height
}
}
var arr1 = [1,2,3]
Array.prototype.aa = 'aa'
arr1.bb = 4
for(let i in arr1) {
// console.log(i) // -> 0 1 2 bb aa
}
for (let i of arr1) {
// console.log(i) // -> 0 1 2
}
Function.prototype.myCall = function(context) {
if (typeof this !== 'function') {
throw new Error('type error')
}
let arg = [...arguments].slice(1), result = null
context = context || window
context.fn = this
result = context.fn(...arg)
delete context.fn
return result
}
Function.prototype.myApply= function(context) {
if (typeof this !== 'function') {
throw new Error('type error')
}
let arg = [...arguments].slice(1), result = null
context = context || window
context.fn = this
result = context.fn(arg)
delete context.fn
return result
}
Function.prototype.myBind= function(context) {
if (typeof this !== 'function') {
throw new Error('type error')
}
let args = [...arguments].slice(1), fn = this
return function Fn() {
// 根据调用方式,传入不同绑定值
return fn.apply(
this instanceof Fn ? this : context,
args.concat([...arguments])
)
}
}
// 字符串出现的不重复最长长度
function lengthOfLongestSubstring(str) {
let map = new Map(), i = -1, res = 0, n = str.length
for(let j = 0; j < n; j++) {
if (map.has(str[j])) {
i = Math.max(i, map.get(str[j]))
}
res = Math.max(res, j - i)
map.set(str[j], j)
}
return res
}
// console.log(lengthOfLongestSubstring('bwabfwb'))
// 将数字每千分位用逗号隔开
function formatNum(n) {
let num = n.toString(),
intNum = num,
decimals = '',
index = num.indexOf('.')
if (index > -1) {
[intNum, decimals] = num.split('.')
// decimals = num.split('.')[1]
// intNum = num.slice(0, index)
}
if (intNum.length <= 3) return num
let intNumArr = intNum.split('').reverse(),
lastIndex = intNumArr.length - 1,
tempArr = []
intNumArr.forEach((item, index) => {
tempArr.push(item)
if (index > 0 && index % 3 === 2 && index < lastIndex) {
tempArr.push(',')
}
})
intNum = tempArr.reverse().join('')
return decimals ? intNum + '.' + decimals : intNum
}
// console.log(formatNum(344412323.33)) // -> 344,412,323.33
// 交换a,b的值,不能用临时变量
var a = 3, b = 2
// 巧妙的利用两个数的和、差:
a = a + b
b = a - b
a = a - b
// console.log(a, b)
// 实现数组的乱序输出 -> 方案1
var arr = [1,2,3,4,5,6,7,8,9,10];
let length = arr.length,
randomIndex,
temp;
while (length) {
randomIndex = Math.floor(Math.random() * length--);
[arr[length], arr[randomIndex]] = [arr[randomIndex], arr[length]];
}
// console.log(arr, arr.length)
// 实现数组的乱序输出 -> 方案2
var arr = [1,2,3,4,5,6,7,8,9,10], lastIndex = arr.length - 1;
for (var i = 0; i <= lastIndex; i++) {
const randomIndex = Math.round(Math.random() * (lastIndex - i)) + i;
[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
}
// console.log(arr, arr.length)
var arr = [1,2,3,4,5,6,7,8,9,10]
var sum = arr.reduce((sum, next) => sum += next, 0)
// console.log(sum) // -> 55
function add(arr) {
if (arr.length == 1) return arr[0]
return arr[0] + add(arr.slice(1))
}
// console.log(add(arr)) // -> 55
var arr = [1,2,3,[[4,5],6],7,8,9]
// console.log(arr.toString(), arr.toString().split(','))
var sum = arr.toString().split(',').reduce((total,i) => total += Number(i),0);
// console.log(sum); // -> 45
var arr = [1, [2, [3, [4, 5]]], 6];
function flatten(arr) {
let str = JSON.stringify(arr);
str = str.replace(/(\[|\])/g, '');
str = '[' + str + ']';
return JSON.parse(str);
}
// console.log(flatten(arr));
function flatten(arr) {
return arr.flat(Infinity);
}
// console.log(flatten(arr));
function flatten(arr) {
return arr.toString().split(',');
}
// console.log(flatten(arr));
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
// console.log(flatten(arr));
function flatten(arr) {
return arr.reduce(function(prev, next){
return prev.concat(Array.isArray(next) ? flatten(next) : next)
}, [])
}
// console.log(flatten(arr));
function flatten(arr) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
// console.log(flatten(arr));
function _flat(arr, depth) {
if (!Array.isArray(arr) || depth <= 0) {
return arr
}
return arr.reduce((prev, cur) => {
if(Array.isArray(cur)) {
return prev.concat(_flat(cur, depth - 1))
} else {
return prev.concat(cur)
}
}, [])
}
function add(m) {
var temp = function(n) {
return add(m + n)
}
temp.toString = function() {
return m
}
return temp
}
// console.log(add(3)(4)(5))
// function _flat(arr, depth) {
// if(!Array.isArray(arr) || depth <= 0) {
// return arr;
// }
// return arr.reduce((prev, cur) => {
// if (Array.isArray(cur)) {
// return prev.concat(_flat(cur, depth - 1))
// } else {
// return prev.concat(cur);
// }
// }, []);
// }
// var arr = [1, [2,3], 4, [5, [6,7]]]
// console.log(_flat(arr, 2))
function _flat(arr, depth = 1){
if(!Array.isArray(arr) || depth <= 0) {
return arr
}
return arr.reduce((prev, cur) => {
if (Array.isArray(cur)) {
return prev.concat(_flat(cur, depth - 1))
} else {
return prev.concat(cur);
}
}, []);
}
// var arr = [1, [2,3], 4, [5, [6,7]]]
// console.log(_flat(arr, 2))
function test(num) {
const chars = num.toString().split('')
const len = chars.length
let index = 0, res = 0
while(index < len) {
res += chars[index] * chars[index]
index++
}
console.log(res)
return res == 1 ? true : test(res)
}
// console.log(test(19))
console