目录

js假值

js表达式&js语句

== 与 ===

一元运算符 与(& &&)或(| ||)非(!)

数据类型

类型转换

递增/减

循环语句

判断是否为数组

函数相关

类与对象的关系

原型链

对象相关


js假值

一共有6个,分别是

null,undefined,false,0,NaN,''

  • NaN不等于任何值,包含本身
NaN===NaN   //false
  • undefined + 任何值 = NaN,除了加字符串。
  • 转换undefined为数字型,也是NaN
  • 字符串转数字,除了数字字符串会转为数字,其他的转换也是NaN
  • parseInt(),转除了数字字符串和数字型以外的,也是NaN
  • parseFloat(),转除了数字字符串和数字型以外的,也是NaN
// 
console.log(1 + undefine) // NaN
console.log('123' + undefined) // 123undefined
// 
console.log(Number(undefined)) // NaN
console.log(undefined - 0) // NaN
// 
let str = '99' // 数字字符串
console.log(Number(str)) // 99
let s = 'a'
console.log(Number(s)) // NaN
// parseInt() 只能转换数字字符串和数字型的,会向下取整
console.log(parseInt('123')) // 123
console.log(parseInt(99)) // 99
console.log(parseInt(99.99)) // 99
console.log(parseInt('a')) // NaN
console.log(parseInt(true)) // NaN
console.log(parseInt(null)) // NaN
console.log(parseInt(undefined)) // NaN
// parseFloat() 也是只能转换数字字符串和数字型的,但是会保留小数
console.log(parseFloat('123.09')) // 123.09
console.log(parseFloat(99)) // 99
console.log(parseFloat(99.99)) // 99.99
console.log(parseFloat('a')) // NaN
console.log(parseFloat(true)) // NaN
console.log(parseFloat(null)) // NaN
console.log(parseFloat(undefined)) // NaN

js表达式&js语句

表达式就是会产生一个结果(值)的代码,可以写在右侧

let count = 10 + 20 // 右面就是一个表达式,会产生一个具体的值

语句就是一段可执行的代码(for,if,log,dir,alert...)

for(let i = 0;i < 9;i++) { console.log(i) } // 这个就是个js语句,不会产生值,就是执行

== 与 ===

双等只需要值相等,数据类型可以不同

null == undefined // true

三等既需要值相等,数据类型也要相同

null === undefined // false

一元运算符 与(& &&)或(| ||)非(!)

  • & 和 &&(短路与)     全真才为真
// 值对比
console.log(0 & 1) // 0
console.log(0 && true) // 0
// 值与表达式对比
console.log(2 + 5 & 0) // 0
console.log(2 + 5 && 0) // 0
console.log(2 + 5 & false) // 0
// 值与语句对比
0 & console.log('左为假,单&,执行了')     // 输出了,因为单&,前后都会对比,所以不管前面真假都会输出
1 & console.log('左为真,短路&,执行了')   // 输出了,同上
0 && console.log('左为假,单&,执行了')    // 未执行,因为短路&,前面的为假,就不会执行后面的了
1 && console.log('左为真,短路&,执行了')  // 执行了,推荐用这个,可以代替简单的if判断
  • | 和 ‖(短路或)     全假才为假
// 值对比
console.log(0 | 1) // 1
console.log(0 || true) // true
// 值与表达式对比
console.log(2 + 5 | 0) // 7
console.log(2 + 5 || 0) // 7
console.log(2 + 5 | false) // 7
// 值与语句对比
0 | console.log('左为假,单|,执行了')     // 输出了,因为单|,前后都会对比,所以不管前面真假都会输出
1 | console.log('左为真,单|,执行了')   // 输出了,同上
0 || console.log('左为假,短路|,执行了')    // 执行了,推荐用这个,可以代替简单的if判断
1 || console.log('左为真,短路|,执行了')  // 未执行,因为短路|,前面的为真,就不会执行后面的了
  • !取反操作
console.log(!0) // true
console.log(!1) // false
console.log(!true) // false
console.log(!false) // true
console.log(!(99 - 9)) // true

数据类型

基本数据类型

string,number,boolean,undefined,null,symbol

复杂(引用)数据类型

Object(Array,Function),Map,Set

  • 通过 typeof() 判断数据类型

类型转换

转字符串:toString(),'' + 其他(隐式转换),String()

// 数值
let num = 99
console.log(String(num)) // '99'
console.log(typeof (String(num))) // string
// 布尔
let flag = true
console.log(flag + '123') // 'true123'
// undefined
let un = undefined
console.log(String(un)) // 'undefined'
console.log(typeof (String(un))) // string
// 对象,toString是从Object基类继承下来的
const obj = { name: 'zs' }
console.log(obj.toString()) // '[object Object]'
console.log(typeof (obj.toString())) // string

转数字型:Number(),+号(隐式转换),-*/(隐式转换),parseInt(),parseFloat()

// 假值转换成数字型,都会为0
// 布尔
let flag = true
console.log(flag - 0) // 1
// null
let n = null
console.log(+n) // 0
// string,只能转换数字字符串,其他的也是NaN
let str = '99' // 数字字符串
console.log(Number(str)) // 99
let s = 'a'
console.log(Number(s)) // NaN
// undefined,注意这个,这个不管强转还是隐式转换,都是NaN
let un = undefined
console.log(un - 0) // NaN
console.log(Number(un)) // 0
// parseInt() 只能转换数字字符串和数字型的,会向下取整
console.log(parseInt('123')) // 123
console.log(parseInt(99)) // 99
console.log(parseInt(99.99)) // 99
console.log(parseInt('a')) // NaN
console.log(parseInt(true)) // NaN
console.log(parseInt(null)) // NaN
console.log(parseInt(undefined)) // NaN
// parseFloat() 也是只能转换数字字符串和数字型的,但是会保留小数
console.log(parseFloat('123.09')) // 123.09
console.log(parseFloat(99)) // 99
console.log(parseFloat(99.99)) // 99.99
console.log(parseFloat('a')) // NaN
console.log(parseFloat(true)) // NaN
console.log(parseFloat(null)) // NaN
console.log(parseFloat(undefined)) // NaN

转布尔型:Boolean()

// 假值转换成布尔,都会为false
console.log(Boolean(0)) // false
console.log(Boolean(1)) // true
console.log(Boolean(undefined)) // false
console.log(Boolean(null)) // false
console.log(Boolean('a')) // true
console.log(Boolean('')) // false

递增/减

递增递减单独使用

let num = 10
// 前++/--,会先进行自增/减
console.log(++num) // 11
console.log(--num) // 10
// 后++/--,会先进行紧挨的操作,操作完成后再自增/减
console.log(num++) // 10,因为它会先进行输出,输出后(10),num自增(10 + 1),这时num是11
console.log(num--) // 11,因为它会先进行输出,输出后(11),num自减(11 - 1),这时num是10

递增递减参与运算时

  • 前增/减,先自增/减,再参与运算
  • 后增/减,先参与当前次运算,然后再自增/减
let num = 10
// 前++/--,会先进行自增/减
console.log(10 + ++num) // 21,num会先自增(10 + 1),此时的num为11,然后参与运算(10 + (10 + 1))
console.log(10 + --num) // 20,num会先自减(11 - 1),此时的num为10,然后参与运算(10 + (11 - 1))
// 后++/--,会先进行紧挨的操作,操作完成后再自增/减
console.log(10 + num++) // 20,因为它会先进行运算(10 + 10),输出后(20),num自增(10 + 1),这时num是11
console.log(num) // 11
console.log(10 + num--) // 21,因为它会先进行运算(10 + 11),输出后(21),num自减(11 - 1),这时num是10
console.log(num) // 10

练习:

let num = 10
let res = num++ + 10 - num-- + ++num
// 1. num + 10 = 20  num = 11
// 2. 20 - 11 = 9  num = 10
// 3. 9 + 11 = 20 num = 11
console.log(res) // 20

循环语句

switch...case

  • 一般用于等值运算,不适合区间判断
let i = 2
switch (i) {
    case 0:
        console.log(0);
        break;
    case 1:
        console.log(1);
        break;
    case 2:
        console.log(2);
        break;
     default:
        console.log('...');
        break;
}

for

  • 适合不确定次数的,并且不会跳过假值,里面的变量是局部变量
for (var i = 0; i < 10; i++) {
    console.log(i);
}
// 不会跳过假值
const arr = [, , , , ,]
for (let i = 0; i < arr.length; i++) {
    arr[i] = 'a' + i
}
console.log(arr) // ['a0', 'a1', 'a2', 'a3', 'a4']

while

  • 适合确定次数的
let i = 0
while (i < 3) {
    console.log(i)
    i++
}

无限循环

while(true) {}      或     for(;;;){}

判断是否为数组

  1. Array.isArray(),会返回一个布尔值
  2. insranceOf 运算符,会判断是否在其原型链上
let arr = [1, 2, 3]
// Array.isArray(arr)
console.log(Array.isArray(arr)) // true
// instanceof 运算符
console.log(arr instanceof Array) // true

函数相关

函数的参数可以传入默认值

function 函数名(参数名 = 默认值){ 函数体 }

形参当成局部变量

unction fn(args) {
    return args
}
console.log(fn(99)) // 99
console.log(args) // 会直接报错的,因为形参是局部变量,只能函数体内用。args is not defined

return返回一个值,如果想返回多个值,用数组或对象

// 只能返回第一个,因为遇到return,就会终止函数
function fn() {
    return '99'
    return 0
}
console.log(fn()) // '99'
// 需要返回很多数据时,最好用对象或数组
function fun() {
    return {
        xx: 0,
        xxx: 1,
        xxxx: 2,
        // ...
    }
}
console.log(fun()) // {xx: 0, xxx: 1, xxxx: 2}
function f() {
    return [1, { xx: 0 }, 'pink', '4']
}
console.log(f()) // [1, {…}, 'pink', '4']

return结束的是函数,break结束的是循环,contation跳出的是本次循环

// return 终止的是函数
function fn() {
    let num = 10
    num++
    num--
    return num
}
console.log(fn()) // 10
// breack 终止的循环
for (let i = 0; i < 10; i++) {
    if (i === 5) {
        console.log('到5就结束了')
        break
    }
}
// continue 跳出的是本次循环
for (let i = 0; i < 10; i++) {
    if (i === 3) {
        continue
    }
    console.log(`第${i}次执行`)
}

函数如果不确定有多少参数

  • 可以用arguments,函数内置的,以伪数组形式存储,不需要写在参数里
function fn() {
    console.log(arguments)
    // arguments以伪数组形式进行存储
    console.log(Array.isArray(arguments)) // false
    // 伪数组是用不了真数组的方法的,如果我们想用真数组的方法,需要把它转成真数组(Array.from())
    // arguments.forEach(item => {
    //     console.log(item) // 用不了真数组的方法
    // })
    console.log(Array.from(arguments)) // [10, 20, 30, 40, 50]
    // 可以用循环正常遍历,伪数组存在length属性
    for (let i = 0; i < arguments.length; i++) {
        console.log(`伪数组第${i}项:`, arguments[i])
    }
    // 不写return,默认返回undefined
    // return
}
fn(10, 20, 30, 40, 50)
  • 还可以用剩余(rest)参数,需要写在参数里fun(...args){},或fun(a,b,...args){}
function fn(...args) {
    // 是真数组呦
    console.log(args[0]) // 10
    console.log(args[1]) // 20
    // ...
}
fn(10, 20, 30, 40, 50)
function fun(num1, num2, ...args) {
    console.log(num1) // 10
    console.log(num2) // 20
    console.log(args[0]) // 30
}
fun(10, 20, 30, 40, 50)

作用域

  • 分为全局作用域和局部作用域,域就是块,可以理解为代码可执行的范围,再简单理解,就是{}包住的
  • 域的出现,主要是为了解决命名的问题,有效防止了命名冲突,不同域里可以写同名变量,互不影响
// 全局作用域,全局生效
let num = 100 // 全局变量
function fn() { // 全局函数
    // 局部作用域,只在块(域)内生效
    let num = 99 // 局部变量
    console.log(num) // 99
    return function () { // 局部函数
        return num
    }
}
// 全局函数,全局都可以进行调用
fn() // 99
let res = fn()()
console.log(res) // 99(第一个99,是外层函数打印的) 99(第二个99,是调用闭包,接收的变量值为99)

函数分为具名函数(普通函数)和匿名函数(函数表达式)

  • 普通函数,具有函数提升,可以放在任何位置
// 具有函数提升
let res = fn()
console.log(res) // 99
// 普通函数
function fn() {
    return 99
}
  • 函数表达式,把函数用一个变量接收,必须先声明,再调用
// 函数表达式,用变量接收函数
const fn = function () {
    return 100
}
console.log(fn()) // 100
const fun = () => {
    return 99
}
console.log(fun()) // 99
  • 还有一种特殊函数,立即执行函数(立即执行函数):末尾一定写分号(不然他会以为不是结尾,跟下面代码混一块啦)

(function(){})() ; 或  (function(){}());

  • 箭头函数,本身没有this指向,会找它上一个作用域的this赋值给自身,只要第一次确认了,后面就不会变
const obj = {
    name: 'zs',
    sing: function () {
        console.log(this) // {name: 'zs', sing: ƒ, dance: ƒ}
    },
    dance: () => {
        console.log(this) // window
    }
}
// 对象的方法,如果是普通函数,this指向对象本身
obj.sing()
// 如果是箭头函数,则指向window
obj.dance()

类与对象的关系

类是抽象的,包含了一大类,抽离了一些这一类公有的属性和行为

es6之前的类,表现形式就是构造函数

// 构造函数首字母大写,用于与普通函数做区分(推荐首字母大写)
        function Person(name, age, gender) {
            // 属性
            this.name = name
            this.age = age
            this.gender = gender
            // 行为
            this.say = function (language) {
                return '会说' + language
            }
        }
        // 想要使用构造函数,需要new关键字
        let zs = new Person('张三', 24, '男')
        console.log(zs) // Person {name: '张三', age: 24, gender: '男', say: ƒ}
        console.log(zs.say('中文')) // 会说中文

es6新增了类class

// 类名首字母大写
        class Person {
            // 属性
            constructor(name, age, gender) {
                this.name = name
                this.age = age
                this.gender = gender
            }
            // 行为
            say(language) {
                return `会说${language}`
            }
        }
        // 使用类,也需要new关键字,new就是new出来一个具体的,真实存在的对象
        const ls = new Person('李四', 24, '男')
        console.log(ls) // Person {name: '李四', age: 24, gender: '男'}
        console.log(ls.say('中文')) // 会说中文

我们new一个类,就会得到一个具体的对象,对象是具体的,真真实实存在的。打个比方,例如人类,就是一个大类,类里面存放一些人类共有的属性(名词)和行为(动词),然后,我,就是一个实实在在的人,就是一个对象。通过new 人类,就会得到一个具体的对象

原型链

作用:

  • 用来存放一些公用的属性和方法

谁存在原型:

  • 函数与对象都是有原型的
  • 函数有显示原型prototype
  • 对象有隐式原型__proto__

我们new一个构造函数或者类,就会得到一个新的对象,构造函数的prototype其实就等于new出来这个对象的__proto__

图解

代码

// 构造函数
        function Person(name, age, gender) {
            this.name = name
            this.age = age
            this.gender = gender
            this.say = function (language) {
                return '会说' + language
            }
        }
        console.log(Person.prototype) // {constructor: ƒ}
        console.log(Person.prototype.constructor) // 指回构造函数
        console.log(Person.prototype.constructor === Person) // true
        // new出来的实例化对象
        const ls = new Person('李四', 24, '男')
        console.log(ls.__proto__) // {constructor: ƒ}
        console.log(Person.prototype === ls.__proto__) // true
        console.log(ls.__proto__.constructor) // 指回构造函数

原型查找机制:

对象本身查找-->去创建当时对象的构造函数中查找-->去对象的原型中查找-->去构造函数的原型中查找-->去原型的原型中查找直到查找到null

图解

代码

// 构造函数
function Person(name, age, gender) {
    this.name = name
    this.age = age
    this.gender = gender
    this.say = function (language) {
        return '会说' + language
    }
}
console.log(Person.prototype) // {constructor: ƒ}
console.log(Person.prototype.constructor) // 指回构造函数
console.log(Person.prototype.constructor === Person) // true
// new出来的实例化对象
const ls = new Person('李四', 24, '男')
console.log(ls.__proto__) // {constructor: ƒ}
console.log(Person.prototype === ls.__proto__) // true
console.log(ls.__proto__.constructor) // 指回构造函数
// 但是实例化对象的隐式原型__proto__(又叫原型对象,也是个对象)也存在原型。这样一层一层往上查找,形成一条原型链,直到指向null
console.log(ls.__proto__.__proto__.__proto__) // null

原型链的最顶端是null

对象相关

遍历对象

  • 推荐for...in,不能用for...of(因为对象内置没有Iterator,用不了,非要用,就手动添加Iterator)
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () {
                return '唱'
            }
        }
        for (const key in obj) {
            console.log(key) // 对象的键名
            console.log(obj[key]) // 对象的值名
        }

访问对象属性

  • 对象名.访问
const obj = { name: 'zs', age: 24, gender: '男', }
console.log(obj.name) // 'zs'
  • 对象名['属性名']   , 对象名[变量名]访问,这种适合属性名为变量的,动态的
const obj = { name: 'zs', age: 24, gender: '男', }
// 对象名['键名']
console.log(obj['age']) // 24
// 对象名[变量名]
let key = 'gender'
console.log(obj[key]) // '男'

对象的键名是字符串,只是默认省略了。如果对象的键中有-,则就需要用引号包住啦

const obj = { name: 'zs', age: 24, gender: '男', 'sing-dance-rap': '唱跳rap' }
console.log(obj['sing-dance-rap']) // '唱跳rap'

对象中如果不存在某属性,会输出undefined

const obj = { name: 'zs', age: 24, gender: '男' }
console.log(obj.sing) // undefined

对象中不存在某属性,但是直接给这个属性赋值,则对象中就会添加此属性

const obj = { name: 'zs', age: 24, gender: '男' }
obj.sing = '唱'
console.log(obj['sing']) // 唱

in运算符

  • 可以判断对象中是否存在某属性
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () { return '唱' }
        }
        console.log(name in obj) // true
        // console.log(dance in obj) // 会报错

对象的一些方法

  • Object.keys(对象名)    会返回对象的键组成的数组
const obj = {
            name: 'zs',
            age: 24,
            gender: '男'
        }
        let keys = Object.keys(obj)
        console.log(keys) // ['name', 'age', 'gender']
  • Object.values(对象名)     会返回对象的值组成的数组
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () { return '唱' }
        }
        let values = Object.values(obj)
        console.log(values) // ['zs', 24, '男', ƒ]
  • Object.assign(对象名)     会拷贝对象,是浅拷贝
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () { return '唱' }
        }
        let newObj = Object.assign(obj)
        console.log(newObj) // {name: 'zs', age: 24, gender: '男', sing: ƒ}
        // 是浅拷贝
        console.log(obj === newObj) // 因为地址相同,所以为true,浅拷贝
  • Object.entries(对象名)     会返回对象键值对的数组
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () { return '唱' }
        }
        let keysValues = Object.entries(obj)
        console.log(keysValues)
  • Object.fromEntries(对象名)     可以把二维数组转换成对象,与Object.entries(对象名) 方法互逆操作
const obj = {
            name: 'zs',
            age: 24,
            gender: '男',
            sing: function () { return '唱' }
        }
        let keysValues = Object.entries(obj)
        console.log(keysValues)
        let newObj = Object.fromEntries(keysValues)
        console.log(newObj) // {name: 'zs', age: 24, gender: '男', sing: ƒ}

原文链接:https://blog.csdn.net/qq_52845451/article/details/129721480

最后修改:2023 年 10 月 30 日
如果觉得我的文章对你有用,请随意赞赏