2 Function

172 阅读9分钟

问题回顾

  • 'a'-'a' NaN ==字符串转化为数NaN 转化为布尔 空0 非空1==

  • ==''-'' 0==

  • null == undefined true

  • null === undefined false null object undefined undefined

    console.log('aa' == true)
    //false
    console.log('true' == true)
    //false
    console.log('1' == true)
    //true
    //任何值和布尔等于 toNumber(boolean)
    
    //判断闰年
    (x % 400 == 0) ||((x % 4 == 0) && (x % 100 != 0))
    //判断100以内质数
    (x != 2 && x % 2 == 0)||(x != 3 && x % 3 == 0)||(x != 5 && x % 5 == 0)||(x != 7 && x % 7 == 0)
    
    NaN = 888
    undefined = 999
    //可以赋值 但值不变
    

Equality Comparison

  • x==y

  • ‘aa’==3 false aa转换成NaN

  • asi auto semicolon insert
    • 当一行的第一个字符是+ - / [ ( 这几个符号时 他前面一行必须加分号
    • 前置分号 foo ;(2+3)

变量声明及赋值语句

  • 变量名不能包含空格 变量名不能以数字开头 不能包含标点符号 可以包含$和_

  • function 的类型为function

    console.log

    获取console 变量的log属性

  • Math.trunc()

    Math.floor()

    Math.ceil()

    Math.max(1,3,4)

    Math.round() 四舍五入

  • confirm() 返回boolean prompt('您的年龄?',"28")

  • alert()

var x = +prompt()
//将string 转换为 number
var a = 1,b=2,c=3;
var z=(a+1,b+2,a+b)
z=3
  • Number() 把参数转换为数字并返回

    null 0

    undefined NaN

    '' 0

    'FADS' NaN

    console.log(a)
    //3.14
    console.log(typeof (a))
    //string
    
  • isNaN 是否是一个数值类型的值/不能被转换为数值

    is Not a Number

    ‘fasa’ true

    NaN true

    ‘ ’ false

    Number.isNaN()

    是否是NaN这个值

整数在计算机中的表示

  • 方便计算减法

    5 - 3 = 5 + (-3)

    0101

    1101

    0010

  • -99 怎么表示 2 ^31^-99 写成2进制 前面加1即可 2 ^31^-1-99 +1 取反加一

  • 000 +8 =8 001+ 7 =8 010 +6 = 8

位运算符

  • 只支持整数 先被转换为32位整数

    • 小数会舍掉小数部分
    • 超过32位 会保留右边32位

    a|b 每一位对齐 或运算 只支持整数 转换成32位数 会把小数去掉 保留右边32个比特

    a&b

    ~a 取反 ==符号位也取反==

    a^b 异或 相同为0 不同为1

    a >> 2 保留符号位

    a << 2

    a >>> 2 (不保留符号位)

0b 二进制

a.toString(2) 数字转化为二进制

0x hex

0o 八进制

任何数与自己按位异或都得到0

任何数与0按位异或都将得到自身

2147483649.5|0 取整

0开头的数是八进制

a = 2147483647
console.log(a.toString(2))
//1111111111111111111111111111111
c = 2147483648
console.log(c | 0)
//- 2147483648

a = -5
console.log(a >> 2)
// -2
console.log(a >> 3)
// -1
console.log(a >> 32)
// -5   a>>32%32
console.log(a >> 35)
// -3   a>>35%32
console.log(a >>> 3)
//536870911

let a = 'aAcd'
console.log(a.charCodeAt(0))
//97
console.log(a.charCodeAt(1))
//65

continue 跳出循环体 进行下一次循环

for(fad;fa;跳到这里)

c++ 会改变c的类型 转换成数值类型

c+=1 不转换类型

parseInt('99 fafsdas',16) 153 转换为16进制

switch语句

switch (4) {
  case 1:
    console.log('a')
    break
  default:
    console.log('d')
  case 2:
    console.log('b')
    break
  case 3:
    console.log('c')
    break
}
// d
// b


switch (2) {
  case 1:
    console.log('a')
    break
  case '2':
    console.log('b')
    break
  case 3:
    console.log('c')
    break
  default:
    console.log('d')
}
// d  数字2和字符串2 用的是===

牛顿法求根

x^2^= n 即 f(x) = x^2^ - n

当x= x0 时 切线斜率 k = f(‘x0) =2x0

y = x0^2^ - n

k =( x0^2^ - n ) / ( x0 - x1 )=2x0

x1 = (x0^2^ + n) / 2x0

通过不断迭代逼近根

//使用牛顿法实现平方根的计算
function sqrt(n) {
  var r = n
  //i是迭代次数 精确度
  for (var i = 0; i < 10; i++) {
    r = (r * r + n) / (2 * r)
  }
  return r
}
console.log(sqrt(20))

向下取整
var mySqrt = function(x) {
    var tmp = x;
    while (x * x > tmp)
        x = ((x + tmp / x) / 2) | 0;
    return x;  
};

最大公约数

//求最大公约数 辗转相除法
function largestCommonFactor(m, n) {
  while (m !== n) {
    if (m < n) {
      var t = m
      m = n
      n = t
    }
    m = m - n
  }
  return m
}


function largestCommonFactor(m, n) {
  let t = 1;
  while (t != 0) {
    t = m % n
    m = n
    n = t
  }
  return m
}

函数声明

var square = function (x) {
  return x * x;
}
//等号右面是一个表达式 有求值结果 求值结果就是函数自己
console.log(square(12))


var power = function (base, exponent) {
  var result = 1
  for (var count = 0; count < exponent; count++)
    result *= base;
  return result
}
console.log(power(2, 10))

var a = function() {
  console.log(x) //这里访问了全局的x
}

var a = function() {
  x = 10
  console.log(x) //这里访问了局部的x 屏蔽全局的x
}
  • return 后面没有表达式 返回undefined

  • result 变量在函数每次调用时重新创建

  • 函数局部性 仅仅对参数和函数内部var定义的变量生效

  • 判断2的方 2方2进制形如 10 100 1000 n&(n-1)

    水仙花数

    //水仙花数
    
    //求位宽
    var digitWidth = function (n) {
      let width = 0
      do {
        n = (n - n % 10) / 10
        width++
      } while (n != 0)
      return width
    }
    
    //求a的n次方
    var power = function (a, n) {
      var result = 1
      for (var i = 0; i < n; i++) {
        result *= a
      }
      return result
    }
    
    var isNarcissistic = function (n) {
      var width = digitWidth(n)
      var sum = 0
      var t = n
    
      do {
        var digit = t % 10
        sum += power(digit, width)
        t = (t - digit) / 10
      } while (t != 0)
    
      return (sum == n) ? true : false
    }
    
    //求1000以内的水仙花数
    
    for (var i = 1; i < 1000; i++) {
      if (isNarcissistic(i)) {
        console.log(i)
      }
    }
    
    
    var x = 155
    digitWidth(x)//这里没有传递x进去 传递的是x的值155
    //3
    //x不变仍未155 
    
    var isPrime = function (n) {
      let a = Math.sqrt(n)
      for (i = 2; i <= a; i++) {
        if (n % i == 0) {
          return false
        }
      }
      return true
    }
    
    
    //素数两性定理:大于3的素数只分布在6n+1和6n-1两数列中
    var isPrime = function (n) {
      if (n < 2) {
        return false
      }
      if (n == 2 || n == 3) {
        return true
      }
    
      if (n % 2 == 0) {
        return false
      }
      if (n % 6 !== 5 &&  n % 6 !== 1) {
        return false
      }
    
      let sqrt_n = Math.sqrt(n)
    
      for (let i = 3; i <= sqrt_n; i += 2) {
        if (n % i == 0) {
          return false
        }
      }
      return true
    }
    
    var countPrimes = function (n) {
      var count = 0
      for (let i = 2; i < n; i++) {
        if (isPrime(i)) {
          count++
        }
      }
      return count
    }
    
    //埃拉托斯特尼筛法 画图筛选去掉从2开始 找素数,先留2 然后2*2 去掉4 2*2+2去掉6 8,10 再找3 留3 去掉3*3 3*3+3
    //核心就是去掉2,3,5,7的倍数
    //let signs = new Uint8Array(n);
    //创建长度为n的数组 并且用0填充
    var countPrimes = function (n) {
      let count = 0;
      let signs = new Uint8Array(n);
      
      for (let i = 2; i < n; i++) {
        if (!signs[i - 1]) {
          count++;
    
          for (let j = i * i; j <= n; j += i) {
            signs[j - 1] = true;
          }
        }
      }
      return count;
    };
    
    //判断是否为2的幂
    var isPowerOfTwo = function(n) {
        if(n <= 0) {
            return false
        }
        return (n & (n - 1)) == 0 
    };
    //考虑2进制
    
    //判断是否为2的幂
    return 1162261467 % n == 0
    // 3的19次方 整形能表示的最大的3的幂 只能模3为0
    

    回文数

判断完全平方数

//二分法
var isPerfectSquare = function(num) {
  if(num == 1) return num
  let low = 1
  let high = num
  let middle
  while(high - low > 1) {
      middle = (high + low) / 2 | 0
      if(middle * middle == num){
        return true    
      }
      else {
          (middle * middle > num)? high = middle : low = middle
      }
  }
  return false
};

七进制

var convertToBase7 = function(num) {
    let sum = 0
    let positive = 1
    let base = 1
    if (num < 0) {
        positive = 0
        num = -num
    }
    while(num > 0){
        digit = num % 7
        sum += digit * base
        num = (num - digit) / 7
        base *= 10
    }
    return positive ? sum : -sum
};

判断weekday(某年某月第一天是星期几)

 function isLeapYear(year) {
  if (year % 400 == 0) {
    return true
  }
  if (year % 100 == 0) {
    return false
  }
  if (year % 4 == 0) {
    return true
  }
  return false
}
function weekday(year, month) {
  //公元元年是1年
  var sum = 0
  var y = year - 1
  sum = y * 365 + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400)
  for (var m = 1; m < month; m++) {
    sum += getDayOfMonth(m, year)
  }

  return (sum + 1) % 7
}

function getDayOfMonth(month, year) {
  if (m == 2) {
    if (isLeapYear(y)) {
      return 29
    } else {
      return 28
    }
  } else {
    switch (m) {
      case 1:
      case 3:
      case 5:
      case 7:
      case 8:
      case 10:
      case 12: return 31
      default: return 30
    }
  }
}

作用域

var x = 5
var a = function () {
  x = x + 5
  return x
}
a()
console.log(x)
// 10
var x = 5
var a = function () {
  x = x + 5
  return x
}
a()
console.log(a())
console.log(x)
//15
  • 对于任何一个变量的访问,都从代码中书写该变量的位置开始查找,逐级往上层作用域查找。
function foo() {
  var a = 8
  bar()
}

var a = 9

function bar() {
  console.log(a)
}

foo()
// 9 从bar定义的位置看
  • var只有函数作用域 单纯的{}括起来的不能算作用域 没有块级作用域
  • let 声明的变量有块级作用域 es6
声明提升 hoist
function f() {
  var x = 2
  var digit//提升到了这里
  var i    //提升了
  var x


  x = 2
  for(var i = 1;i < 10;i++) {
    var digit = 5
    // var定义的会提升 指定以一次 digit =5
  }
}


function f () {
  console.log(a)
  //undefined
  var a = 8
  console.log(a)
  //8
}

function f() {
  i = 4
  console.log(i)
  for (var j = 0; j < 1; j++) {
    var i = i + 1
  }
  console.log(i)
}
f()
// 4 5

function f() {
  for (var i = 0; i < 4; i++) {
  }
  console.log(i)
}
f()
// 4

//let 声明的标量是块级作用域
var a = 8
if (true) {
  let a = 9
  a = 10
  console.log(a)
  //10
}
console.log(a)
//8

var a = 8
if (true) {
  a = 10
  console.log(a)
  //10
}
console.log(a)
//10



let a = 8
if (true) {
  var a = 9
  a = 10
  console.log(a)
}
console.log(a)
//会报错 let声明的变量不能再var


function f() {    //Temper Dead Zone  TDZ
  console.log(a)
  let a = 8
  console.log(a) 
}
//报错 不能在初始化变量前访问他


var a = 8
console.log(a * a)

var a = 8
console.log(a * a)

var a = 8
console.log(a * a)

// 64 64 64

let a = 8
console.log(a * a)
let a = 8
console.log(a * a)
//报错
a = function () {
  return 8
}
console.log(Math.max(a, 9))
// NaN a是函数不是返回值  函数可以作为值被传递

a = function () {
  return 8
}
console.log(Math.max(a(), 9))
//9

函数声明

var a = function(){
  //表达式 表达式的求值结果是函数
}

function a {
  //语句 没有求值结果
  // 定义变量a 变量a指向一个函数
  //这种方式定义的方法可以晚于调用 不在正常控制 流中
}

var a = function(){return 8}()
// a = 8 表达式后面() 调用这个函数


//函数声明不要写在if里 如果写 写成这种 不要写成直接声明的
if(true){
  a = function(){
    
  }
}
var a = 8
function a(){
  return 0
}

//a ???

// var a  提升
// function a(){  提升
//   return 0
// }
// a = 8
// a为8
var b = function c() {
  //c只能在这里使用 代表函数自己 递归
}

// 在这里只能使用 b

调用栈

  • 计算机存储上下文(执行环境的地方叫做调用栈) 函数执行完跳到那里去 2.函数间的关系

可选参数值

  • 传的参数多了,会被忽略,传的参数少了会被分配undefined
function power(base, exponent) {
  if (exponent == undefined)
    exponent = 2;
  var result = 1;
  for (var count = 0; count < exponent; count++)
    result *= base;
  return result;
}
  • 所有参数被放在arguments 这个只能在函数内部访问的特殊变量中。arguments[0]表示第一个参数,arguements.length 表示实际传入的参数个数,它是一个类数组对象,array like object