let n = 5, num = 1 for (let i = 0; i < n; i++) { num *= 10 } console.log(num)
n的阶乘
1 2 3 4 5 6
let n = 5, num = 1 for (let i = 1; i <= n; i++) { num *= i } console.log(num)
789打印出987
1 2 3 4 5 6
let num = 789 let a = num % 10//9 let b = ((num - a) / 10) % 10//8 // let b = ((num - a) % 100) / 10 let c = (num - a - b * 10) / 100//9 console.log('' + a + b + c)
打印三个数中最大的数
1 2 3 4 5 6 7 8 9 10
let a = 1, b = 2, c = 3 if (a > b) { if (a > c) console.log(a) elseconsole.log(c) } else { if (b > c) console.log(b) elseconsole.log(c) }
打印100以内的质数(仅仅能被1和自己整除的数)
1 2 3 4 5 6 7 8
let c = 0 for (let i = 2; i < 100; i++) { for (let j = 1; j <= i; j++) { if (i % j == 0) c++ } if (c == 2) console.log(i) c = 0 }
// console.log(a) //a is not defined console.log(typeof a) //undefined console.log(typeoftypeof a) //string 数据类型typeof之后再typeof都是string console.log(typeoftypeof123) //string
封装typeof
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
functionmyTypeof(val) { let type = typeof val let toStr = Object.prototype.toString let res = { '[object Array]': 'array', '[object Object]': 'object', '[object Number]': 'number', '[object String]': 'string', '[object Boolean]': 'boolean', } if (val === null) { return'null' } elseif (type === 'object') { let ret = toString.call(val) return res[ret] } else { return type } }
显示类型转换
Number
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// let a = '123' // console.log(typeof Number(a) + '--' + Number(a)) //number--123 // let a = true // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--1 // let a = false // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--0 // let a = null // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--0 // let a = undefined // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--NaN // let a = 'a' // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--NaN // let a = '1a' // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--NaN // let a = '3.14' // console.log(typeof Number(a) + '--' + Number(a)) //nnumber--3.14
parseInt
1 2 3 4 5 6 7 8 9 10 11 12
// let a = '123' // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--123 // let a = '1.23' // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--1 // let a = '1.99' // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--1 // let a = true // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--NaN // let a = null // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--NaN // let a = undefined // console.log(typeof parseInt(a) + '--' + parseInt(a)) //nnumber--NaN
1 2 3 4
let a = '10' console.log(parseInt(a, 16)) //16 //第二个参数取值2-36 console.log(parseInt('abc123')) //NaN console.log(parseInt('123abc1')) //123
parseFloat
1 2 3 4
let num = parseFloat('2.345') let num2 = parseFloat('2') console.log(num.toFixed(2)) //2.35 四舍五入保留两位小数 console.log(num2.toFixed(2)) //2.00 保留两位小数
toString
null和undefined没有toString方法
1 2 3 4 5 6
// let str = null // console.log(str.toString())//Cannot read properties of null (reading 'toString') // let str = undefined // console.log(str.toString()) //Cannot read properties of undefined (reading 'toString') let str = '123' console.log(str.toString()) //123
Boolean
undefined、null、NaN、” “、0是false,其他都是true
1
console.log(Boolean(1)) //ture
隐式类型转换
a未定义,但是typeof a 是字符串 ‘’undefined’’
1 2
console.log(a) //a is not defined console.log(typeof a) //undefined
1 2 3
let a = '1' a++ //Number(a) 进行了隐式类型转换 console.log(a) //124
console.log(a) //Cannot access 'a' before initialization let a = 1
1 2 3 4 5 6 7
//打印的是函数a console.log(a) //ƒ a(a) {var a = 1;var a = function () {}} functiona(a) { var a = 1 var a = function () {} } var a = 2
暗示全局变量
全局作用域下,未声明或者var声明的变量都会挂载到window下
1 2 3 4 5 6 7 8
var a = 1 b = 2 console.log(window.a) //1 //在全局下不管是否var a=window.a b=window.b // window={ // a:1, // b=2 // }
函数内未声明的变量直接挂载到window下
1 2 3 4 5 6 7 8 9 10
functiontest() { var a = b = 1//a先声明后赋值一个1,然后赋值给b,b未声明 //b 未声明直接挂载到window 全局域下 } test() //访问对象不存在的属性会 undefined console.log(window.a) //undefined console.log(window.b) //1 //访问对象不存在的变量会 not defined console.log(a) //a is not defined
functiontest(a) { console.log(1, a) var a = 1 console.log(2, a) functiona() {} console.log(3, a) var b = function () {} console.log(4, b) functiond() {} } test(2) // 1 ƒ a() {} // 2 1 // 3 1 // 4 ƒ () {}
functiontest(a, b) { console.log(1, a) c = 0 var c a = 5 b = 6 console.log(2, b) functionb() {} functiond() {} console.log(3, b) } test(1) // 1 1 // 2 6 // 3 6
var b = 3 console.log(1, a) functiona(a) { console.log(2, a) var a = 2 console.log(3, a) functiona() {} var b = 5 console.log(4, b) } a(1) // 1 ƒ a(a) { // console.log(2, a) // var a = 2 // console.log(3, a) // function a() {} // var b = 5 // console.log(4, b) // } // 2 ƒ a() {} // 3 2 // 4 5
a = 1 functiontest() { console.log(1, a) a = 2 console.log(2, a) var a = 3 console.log(3, a) } test() var a // 1 undefined //就近原则,函数内部声明了a,所以不去全局找a // 2 2 // 3 3
a = 1 functiontest(e) { functione() {} arguments[0] = 2 console.log(e) //2 if (a) { // a 1 var b = 3 } var c a = 4 var a console.log(b) //undefined f = 5 console.log(c) //undefined console.log(a) //4 } var a test(1) console.log(a) //1 console.log(f) //5 // 2 // undefined // undefined // 4 // 1 // 5
functiona() { functionb() { functionc() {} c() } b() } a() //a定义:a.[[scope]] -> 0 : GO //a执行:a.[[scope]] -> 0 : GO // 1 : GO //b定义:b.[[scope]] -> 0 : a -> AO // 1 : GO //b执行:b.[[scope]] -> 0 : b -> AO // 1 : a -> AO // 2 : GO //c定义:c.[[scope]] -> 0 : b -> AO // 1 : a -> AO // 2 : GO //c执行:c.[[scope]] -> 0 : c -> AO // 1 : b -> AO // 2 : a -> AO // 3 : GO
//c结束:c.[[scope]] -> 0 : b -> AO // 1 : a -> AO // 2 : GO //b结束:b.[[scope]] -> 0 : a -> AO // 1 : GO // c.[[scope]] X //a结束:a.[[scope]] -> 0 : GO // b.[[scope]] X
functiontest1() { functiontest2() { var b = 2 console.log(a) //1 } var a = 1 return test2 //test1执行结束,test1自己的AO销毁,返回test2, //当test1赋值到全局的test3时,test2被挂载到全局GO } var c = 3 var test3 = test1() //此处返回的是函数test2。test2中包含test1的AO,可以访问到test1内部的变量 test3() //test3执行结束时,test2也结束,test2的AO销毁,但是test1的AO未断开, //再执行test3仍可以操作test1的变量
functiontest() { let num = 0 let compute = { add: function () { num++ console.log(num) }, minus: function () { num-- console.log(num) }, } return compute } let compute = test() compute.add() //1 compute.add() //2 compute.minus() //1
构造函数闭包
构造函数被实例化时,内部产生一个this,最后隐式返回this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
functionCompute() { let num = 10 this.add = function () { num++ console.log(num) } this.minus = function () { num-- console.log(num) } //return this //构造函数被实例化时,内部产生一个this,最后隐式返回this } let compute = new Compute() compute.add() //11 compute.add() //12 compute.minus() //11
闭包中的this对象
在闭包中使用 this 会让代码变复杂。 如果内部函数没有使用箭头函数定义,则 this 对象会在运行时绑定到执行函数的上下文。 如果在全局函数中调用,则 this 在非严格模式下等于 window,在严格模式下等于 undefined。 如果作为某个对象的方法调用,则 this 等于这个对象。 匿名函数在这种情况下不会绑定到某个对象,这就意味着 this 会指向 window,除非在严格模式下 this 是 undefined。 不过,由于闭包的写法所致,这个事实有时候没有那么容易看出来。
1 2 3 4 5 6 7 8 9 10
window.identity = 'The Window' let object = { identity: 'My Object', getIdentityFunc() { returnfunction () { returnthis.identity } }, } console.log(object.getIdentityFunc()()) // 'The Window'
为什么匿名函数没有使用其包含作用域(getIdentityFunc())的 this 对象呢? 每个函数在被调用时都会自动创建两个特殊变量:this 和 arguments。内部函数永远不可能直接访问外部函数的这两个变量。但是,如果把 this 保存到闭包可以访问的另一个变量中, 则是行得通的。
1 2 3 4 5 6 7 8 9 10 11
window.identity = 'The Window' let object = { identity: 'My Object', getIdentityFunc() { let that = this returnfunction () { return that.identity } }, } console.log(object.getIdentityFunc()()) // 'My Object'
在定义匿名函数之前,先把外部函数的 this 保存到变量 that 中。然后在定义闭包时,就可以让它访问 that,因为这是包含函数中名称没有任何冲突的一个变量。即使在外部函数返回之后,that 仍然指向 object,所以调用 object.getIdentityFunc()() 就会返回”My Object”
立即执行函数
自动执行,执行完成之后立即释放 立即执行函数 IIFE - immediately-invoked function ()括号包起来的都叫表达式,一定是表达式才能被执行符号执行
functionTest() { //new的时候构造函数内部产生成this,生成原型链 // let this = { // __proto__: Test.prototype // } this.name = '123' } let test = new Test() // new 之前this指向window // AO = { // this: window // }
functioncreatePerson(name, age, job) { let o = newObject() o.name = name o.age = age o.job = job o.sayName = function () { console.log(this.name) } return o } let person1 = createPerson('Nicholas', 29, 'Software Engineer') let person2 = createPerson('Greg', 27, 'Doctor')
实例化原理
自定义构造函数(构造函数模式)
建议大驼峰,区别于普通函数 构造函数模式和工厂模式的区别
没有显式地创建对象。
属性和方法直接赋值给了 this。
没有 return。
在对象实例化之前,this指向window,实例化对象之后,this指向实例化的那个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//类似构造工厂,此时没有实例化,this指向window functionTeacher() { this.name = '张三'//此处this没有指向,谁new之后才指向谁 this.sex = '男' this.smoke = function () { console.log('I am smoking') } } let teacher1 = new Teacher() //实例化对象之后,此时this指向teacher1 let teacher2 = new Teacher() //此时this指向teacher2 teacher1.name = '李四' //实例化的两个对象修改属性互不干扰 console.log(teacher1, teacher2) // Teacher {name: '李四', sex: '男', smoke: ƒ} // Teacher {name: '张三', sex: '男', smoke: ƒ}
也可以传参,解决创建多个类似对象的问题
1 2 3 4 5 6 7 8 9 10 11 12
functionPerson(name, age, job) { this.name = name this.age = age this.job = job this.sayName = function () { console.log(this.name) } } let person1 = new Person('Nicholas', 29, 'Software Engineer') let person2 = new Person('Greg', 27, 'Doctor') person1.sayName() // Nicholas person2.sayName() // Greg
functionCar(color, brand) { let me = {} me.color = color me.brand = brand return me } let car = Car('red', 'Mazda') console.log(car.color) // red console.log(car.brand) // Mazda
显示返回一个值
返回原始值没有用
1 2 3 4 5 6 7 8
functionCar() { this.color = 'red' this.brand = 'Mazda' // return 123 //Car {color: 'red', brand: 'Mazda'} return'abc'//Car {color: 'red', brand: 'Mazda'} } let car = new Car() console.log(car)
返回引用值就会覆盖
1 2 3 4 5 6 7 8 9
functionCar() { this.color = 'red' this.brand = 'Mazda' // return ['1'] //['1'] // return {} //{} returnfunctionname() {} //ƒ name() {} } let car = new Car() console.log(car)
let name = 'abc' name += 10//'abc10' let type = typeof name //'string' if (type.length === 6) { //true type.text = 'string'//new String(type).text='string'原始值包装类,但是无法保存 //delete } console.log(type.text) //undefined
提前包装类,转换成String对象,之后就可以添加属性
1 2 3 4 5 6 7 8
let name = 'abc' name += 10//'abc10' let type = newString(typeof name) //直接包装类,打印出字符串 string if (type.length === 6) { //true type.text = 'string'//type已经是string对象可以添加属性 } console.log(type.text) //string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
functionTest(a, b, c) { let d = 1 this.a = a this.b = b this.c = c functionf() { d++ console.log(d) } this.g = f //return this; 隐式return this 形成了闭包。 //AO里含有d,所以之后就能访问到 } let test1 = new Test() test1.g() //2 test1.g() //3 let test2 = new Test() test2.g() //2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var x = 1, y = (z = 0) functionadd(n) { return (n = n + 1) } y = add(x) functionadd(n) { return (n = n + 3) } z = add(x) console.log(x, y, z) //1 4 4 // GO = { // x: 1, // y: 0, // z: 0, // add:function add(n) {return n=n+3} //重名覆盖了 // }
Teacher.prototype.name = 'Mr.Z' functionTeacher() {} functionStudent() {} inherit(Student, Teacher) let s = new Student() let t = new Teacher() console.log(s) console.log(t)
functionCompute() { this.plus = function (a, b) { console.log(a + b) } this.minus = function (a, b) { console.log(a - b) } } functionFullCompute() { Compute.apply(this) this.mul = function (a, b) { console.log(a * b) } this.div = function (a, b) { console.log(a / b) } } let compute = new FullCompute() compute.plus(1, 1) //2 compute.minus(1, 1) //0 compute.mul(1, 1) //1 compute.div(1, 1) //1
functionTest() { //new的时候构造函数内部产生成this,然后生成__proto__被赋值构造函数的prototype,生成原型链 // let this = { // __proto__: Test.prototype // } this.name = '123' } let test = new Test() // new 之前this指向window // AO = { // this: window // }
var a = 5 functiontest() { a = 0 console.log(a) console.log(this.a) var a console.log(a) } test() // 0 5 0 //0和0是自己有的,this.a是window上的 new test() //0 undefined 0 //0和0是自己有的,实例化之后内部产生的this,但是没有给this加上a这个属性
// var b = 5 // function test2() { // b = 0 // console.log(this) // var b // } // new test2() //test2 {} //没有任何属性
functionTest(a, b, c) { let d = 0 this.a = a this.b = b this.c = c functione() { d++ console.log(d) } this.f = e //new之后 // let this={ // f:function () {d++;console.log(d)} // } // return this //隐式return this形成闭包 } // AO = { // d: undefined, //1 // 0 //4 // } let test1 = new Test() test1.f() //1 test1.f() //2 let test2 = new Test() test2.f() //1
三目运算符
普通三目运算
1 2 3 4 5 6 7 8 9 10
let a = 5 // if (a > 0) { // console.log('大于0') // } else { // console.log('小于等于0') // } // //大于0
a > 0 ? console.log('大于0') : console.log('小于等于0') //大于0
三目运算自带return功能
1 2 3
let a = 5 let str = a > 0 ? '大于0' : '小于等于0' console.log(str) //大于0
三目运算嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13 14
let a = 5, str = '' // if (a > 0) { // if (a > 3) { // str = '大于3' // } else { // str = '小于等于3' // } // } else { // str = '小于等于0' // } // console.log(str) //大于3 str = a > 0 ? (a > 3 ? '大于3' : '小于等于3') : '小于等于0' console.log(str) //大于3
try { console.log('正常执行1') //正常执行1 console.log(a) console.log('正常执行2') } catch (e) { // console.log(e) //eferenceError: a is not defined console.log(e.name + ':' + e.message) //ReferenceError:a is not defined } finally { console.log('正常执行3') //正常执行3 }
functiontest1() { let a = 1 returnfunction () { a++ console.log(a) } } let test = test1() test() //2 test() //3 test = null test() //test is not a function