JS基础之函数和内置对象

函数

函数的定义

// 普通函数定义
function f1() {
  console.log("Hello world!");
}

// 带参数的函数
function f2(a, b) {
  console.log(arguments);  // 内置的arguments对象
  console.log(arguments.length);
  console.log(a, b);
}

// 带返回值的函数
function sum(a, b){
  return a + b;
}
sum(1, 2);  // 调用函数

// 匿名函数方式
var sum = function(a, b){
  return a + b;
}
sum(1, 2);

// 立即执行函数
(function(a, b){
  return a + b;
})(1, 2);

ES6里有的箭头函数来简写匿名函数

var f = v => v;
// 等同于
var f = function(v){
  return v;
}

// 当箭头函数不需要参数或者多个参数的时候用()代替
var f = () => 5;
// 等同于
var f = function(){return 5};

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2){
  return num1 + num2;
}

函数的arguments参数

function add(a,b){
      console.log(a+b);
      console.log(arguments.length);
      console.log(arguments);
      console.log(arguments[0]);
}

add(1,2)

函数里的变量

局部变量

在JS函数内部声明的变量都是局部变量,只能在函数内部访问。

也就是说改变量的作用域是函数内部。只要函数运行结束,变量就会被回收。

全局变量

在函数外部声明的,就称为全局变量,这个脚本里的所有函数都能访问这个变量。

变量的生命周期

JS变量的声明周期从它被声明开始,

全局变量会在程序停止的时候被删除。

局部变量会在函数运行结束后被删除。

作用域

变量的寻找顺序,从调用变量的地方开始逐步向最外层找。

下面看几个例子:

1,

var city = "BeiJing";
function f() {
  var city = "ShangHai";
  function inner(){
    var city = "ShenZhen";
    console.log(city);
  }
  inner();
}

f();  //输出结果是?

2,

var city = "BeiJing";
function Bar() {
  console.log(city);
}
function f() {
  var city = "ShangHai";
  return Bar;
}
var ret = f();
ret();  // 打印结果是?

3,

var city = "BeiJing";
function f(){
    var city = "ShangHai";
    function inner(){
        console.log(city);
    }
    return inner;
}
var ret = f();
ret();

ES6的变量声明

ES6新增了变量声明的关键字let, 以及const。

var 来声明变量会存在变量的提升,全局的提升以及函数作用域的提升。

    // 全局变量的提升
    console.log(age);
    var age = 18;
    console.log(age);

    // 函数作用域的提升
    function myFunc() {
        console.log(stu);
        if(1){
            var stu = "lalala";
        }
    }
    myFunc()

    // 可以重复声明
    var age = 32;
    console.log(age)

let 定义一个块级作用域,最小作用域在{} ,并且不存在变量提升。

// console.log(age); 报错
    let age = 18;
    console.log(age);

    // 最小作用域是{}
    function myFunc() {
        // console.log(stu);报错
        if(1){
            let stu = "lalala";
            console.log(stu)
        }
    }
    myFunc()

    // 报错 不可重复声明
    // let age = 32;
    // 但可以重新赋值
    age = 32;
    console.log(age)

const 声明一个常量 不可修改

const app = "APP";
console.log(app);
// app = "APP1" 报错

词法分析

JS在调用函数的那一瞬间,会先进行词法分析。

词法分析的过程:

当函数调用的前一瞬间,会先形成一个激活对象:Active Object(AO)

然后会进行下面三个分析:

  1, 函数参数

    如果有,会将参数赋值给AO,且值为undefined。没有不做任何操作

  2, 函数的局部变量 

    如果有同名的值,则不做任何操作。

    如果没有,把局部变量赋值给AO,值为undefined。

  3,函数声明

    如果AO上有同名的,则将AO上的覆盖。

    如果没有,则不做任何操作

看下下面两个例子:

1,

var age = 18;
function foo(){
  console.log(age);
  var age = 22;
  console.log(age);
}
foo();  // 问:执行foo()之后的结果是?

2,

var age = 18;
function foo(){
  console.log(age);
  var age = 22;
  console.log(age);
  function age(){
    console.log("呵呵");
  }
  console.log(age);
}
foo();  // 执行后的结果是?

 内置对象和方法

JS中所有的事物都是对象:字符串,数字,数组等等,在JS中对象是拥有属性和方法的数据。

这些基本的数据类型,其实都是内置的对象。

那我们看下var s1 = "abc" 和 var s2 = new String("abc")的区别,可以看下这两个变量类型的区别

自定义对象

在js中所有事物都是对象,那我们怎么创建一个对象呢~

JS中对象的本质是键值对的集合(Hash)结构,但只能用字符创作为键。

var a = {"name": "Alex", "age": 18};
console.log(a.name);
console.log(a["age"]);

// 遍历对象中内容
for (var i in a){
  console.log(i, a[i]);
}

创建一个对象的三种方式

<script type="text/javascript">
    // 第一种方式:字面量
    var o1 = {name: 'o1'}
    var o2 = new Object({name: 'o2'})
      // 第二种方式:构造函数
    var M = function (name) { this.name = name; }
    var o3 = new M('o3')
      // 第三种方式:Object.create
    var p = {name: 'p'}
    var o4 = Object.create(p)

  console.log(o1)    
  console.log(o2)
  console.log(o3)
  console.log(o4)
</script>

结果是:

 

我们会发现,每个对象都有一个__proto__属性,这是js创建对象的时候每个对象都有的一个属性。

对象具有属性__proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,

这也保证了实例能够访问在构造函数原型中定义的属性和方法。

方法是个特殊的对象,方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象,

__proto__ 与 prototype

显式原型的作用:用来实现基于原型的继承与属性的共享。

隐式原型的作用:构成原型链,同样用于实现基于原型的继承。

举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着__proto__依次查找。

实现类的功能

我们可以用构造函数的方法来实现类的功能。

// 父类构造函数
var Car = function (loc) {
  this.loc = loc;
};

// 父类方法
Car.prototype.move = function () {
  this.loc ++;
};

// 子类构造函数
var Van = function (loc) {
  Car.call(this, loc);
};

// 继承父类的方法
Van.prototype = Object.create(Car.prototype);
// 修复 constructor
Van.prototype.constructor = Van;
// 扩展方法
Van.prototype.grab = function () {
  /* ... */
};

ES6声明类的方法

class Animal{
    constructor(){
        this.type = "animal"
    }
    says(say){
        console.log(this.type + "says" + say )
    }
}

let animal = new Animal()

animal.says("hello")

class Dog extends Animal{
    constructor(){
        super();
        this.type = "dog";
    }
}

let dog = new Dog()
dog.says("hello")

相对于ES5的类功能的实现,ES6的更加简单。

Date对象

创建Date对象的几种方式以及一些常见方法

//方法1:不指定参数
var d1 = new Date();
console.log(d1.toLocaleString());
//方法2:参数为日期字符串
var d2 = new Date("2004/3/20 11:12");
console.log(d2.toLocaleString());
var d3 = new Date("04/03/20 11:12");
console.log(d3.toLocaleString());
//方法3:参数为毫秒数
var d3 = new Date(5000);
console.log(d3.toLocaleString());
console.log(d3.toUTCString());

//方法4:参数为年月日小时分钟秒毫秒
var d4 = new Date(2004,2,20,11,12,0,300);
console.log(d4.toLocaleString());  //毫秒并不直接显示

Date对象的方法

var d = new Date(); 
//getDate()                 获取日
//getDay ()                 获取星期
//getMonth ()               获取月(0-11)
//getFullYear ()            获取完整年份
//getHours ()               获取小时
//getMinutes ()             获取分钟
//getSeconds ()             获取秒
//getMilliseconds ()        获取毫秒
//getTime ()                返回累计毫秒数(从1970/1/1午夜)

JSON对象

var str1 = '{"name": "Alex", "age": 18}';
var obj1 = {"name": "Alex", "age": 18};
// JSON字符串转换成对象
var obj = JSON.parse(str1); 
// 对象转换成JSON字符串
var str = JSON.stringify(obj1);

Math对象

abs(x)      返回数的绝对值。
exp(x)      返回 e 的指数。
floor(x)    对数进行下舍入。
log(x)      返回数的自然对数(底为e)。
max(x,y)    返回 x 和 y 中的最高值。
min(x,y)    返回 x 和 y 中的最低值。
pow(x,y)    返回 x 的 y 次幂。
random()    返回 0 ~ 1 之间的随机数。
round(x)    把数四舍五入为最接近的整数。
sin(x)      返回数的正弦。
sqrt(x)     返回数的平方根。
tan(x)      返回角的正切。

 

posted @ 2018-12-22 13:20  GGG_XXX  阅读(329)  评论(0)    收藏  举报