JS基础篇

本文围绕JavaScript基础展开,介绍了变量类型(值类型和引用类型)、typeof运算符及隐式类型转换规则。阐述了原型和原型链、作用域和闭包的概念与应用场景,还讲解了异步和单线程的区别、前端异步场景。此外,提及日期和match,以及数组和对象的API使用。

1.变量类型和计算

 值类型和引用类型

值类型有string、number、boolean、undefined、null

引用类型:对象、数组、函数

// 值类型  a把自己的值复制一份给b,a修改了自己存储的100,而b的不改变,还是100
var a = 100;
var b = a;
a = 200;

//100 
console.log(b);

// 引用类型  a把自己的值(这个值为一个对象的地址)复制给b一份,它们的指向相同,所以b改变的时候,a也改变了
var a = {age:20};
var b = a;
b.age = 21

//21
console.log(a.age);

typeof运算符

typeof可以分辨出基本数据类型,但是不能区分引用类型,除了function函数以外

typeof undefined  //undefined
typeof "abc"    //string
typeof 123      //number
typeof true		//boolean
typeof {}		//object
typeof []		//object
typeof null		//object
typeof console.log	//function

变量计算-隐式类型转换

转换规则

不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换。隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等

比较时候的转换原则:

  • 一个是number一个是string时,会尝试将string转换为number

  • 尝试将boolean转换为number,0或1

  • 尝试将Object转换成number或string,取决于另外一个对比量的类型

运算过程的转换代码

  • 字符串与数字相加,变成字符串

  • 字符串与数字相减,变成数字

当JavaScript遇到预期为布尔值的地方(比如if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用Boolean函数。

当JavaScript遇到预期为字符串的地方,就会将非字符串的数据自动转为字符串。系统内部会自动调用String函数。

字符串的自动转换,主要发生在加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。

当JavaScript遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用Number函数。

除了加法运算符有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。

一元运算符也会把运算子转成数值。

字符串拼接

//110,number类型的
var a = 100 + 10

//"10010" string类型的
var b = 100 + '10'

//80 number类型的
var c = "100"-20;

==运算符

==运算符会隐式类型转换

//true  ”100“转换为number 100
100 == "100";

//true ""转化为0
0 == ""

//true  
null ==undefined;

if语句

var a = true
//a转为Boolean true
if(a){
   
   }

var b = 100
//b转为Boolean true
if(b){
   
   }

var c = ""
//c转化为 boolean false
if(c){
   
   }

逻辑运算

JavaScript的逻辑运算符和其他语言(比如:java、c#、c等)有着很大的不同。
其他那些强类型的语言的逻辑运算符参数运算的都是true或false,结果也一定是true或false,很容器理解和记住。
JavaScript的"逻辑运算符"参与运算的可以是任意类型,结果也可能是任意类型,规则及其复杂。

// JavaScript的逻辑运算符和其他语言(比如:java、c#、c等)有着很大的不同。
//其他那些强类型的语言的逻辑运算符参数运算的都是true或false,结果也一定是true或false,很容器理解和记住。
//而JavaScript的"逻辑运算符"参与运算的可以是任意类型,结果也可能是任意类型,规则及其复杂。


// 逻辑与 && 
//js中逻辑与和其他语言不太一样,如果第一个操作数是true(或者能够转为true),计算结果就是第二个操作数,如果第一个操作数是false,结果就是false(短路计算),对于一些特殊数值不遵循以上规则
//0
console.log(10&0)

console.log(undefined && false);//第一个操作数是undefined,结果undefined
console.log(NaN && false);//第一个操作数是NaN,结果NaN
console.log(null && false);//第一个操作数是null,结果null
console.log('' && false);//第一个操作数是空串,结果空串

// 逻辑或 ||
//如果第一个操作数不是false,结果就是第一个操作数,否则结果是第二个操作数。如果第一个操作数能够转为true,结果就是第一个操作数

//”abc“
console.log(""||"abc")

//true
console.log(!window.abc)

// 取反 ! 首先把数据转化为布尔值,然后取反,结果为true或false
var a = 100

//true
console.log(!!a)

答案

JS中使用typeof能得到哪种类型

何时使用===和==

if(obj.a == null){
   //等价于obj.a === null ||obj.a == undefined jQuery
   // 其他全部用===
 }

JS中有哪些内置函数?

Number、String、Boolean、Array、Object、RegExp、Function、Date、Error

JS中有哪些内置对象?

Math和JSON

JS按存储方式区分变量类型

1.值类型

var a = 10;
var b = a;
a = 11;

//10
console.log(b);

2.引用类型

var obj1 = {x:100}
var obj2 = obj1
obj1.x = 200

//200
console.log(obj2.x);

如何理解JSON?

// JSON只不过是一个JS对象而已

JSON.stringify({a:10,b:20})
JSON.parse("{a:10,b:20}")

2.原型和原型链

 构造函数

function Foo(name,age){
    this.name = name;
    this.age = age;
    this.class = "class-1";
    
    //默认会有这行
    //return this;
}

var f = new Foo("zhangsan",20);

构造函数-扩展

原型规则和示例

// 1.所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了null)
var obj = {};
obj.a = 100;

var arr = [];
arr.a = 100;

function(){}
fn.a = 100;

// 2.所有的引用类型(数组、对象、函数),都具有__proto__属性(隐式原型),属性值是一个普通的对象

console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

// 3.所有的函数,都有一个prototype属性(显示原型),其值也为一个普通对象

console.log(fn.prototype);

// 4. 所有的引用类型(数组、对象、函数),__proto__属性指向它的构造函数的prototype属性值

console.log(obj.__proto__ === Object.prototype)

// 5.当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)属性中寻找

//构造函数
function Foo(name){
    this.name = name
}
Foo.prototype.alertName = function(){
    alert(this.name);
}

//创建实例
var foo = new Foo("zhansan);
f.printName = function(){
    console.log(this.name);
}

f.printName();
f.alertName();


//  6.循环对象自身的属性
var f
for(item in f){

    //高级浏览器已经在for in中屏蔽了来自原型的属性
    //但是这里建议大家还是加上这个判断,保证程序的健壮性
    if(f.hasOwnProperty(item)){

       console.log(item);
       }
}

原型链

instanceof

答案

如何准确判断一个变量是数组类型

var arr = [];


//true
arr instanceof Array;

//true
Array.isArray(arr);


//object,是判断不出来的
typeof arr;

//true
Object.prototype.toString.call(arr) === "object Array";


var arr = [];
console.log(arr instanceof Array);
console.log(Array.isArray(arr));
console.log(Object.prototype.toString.call(arr) === "object Array");

写一个原型链继承的例子

function Animal(){
    this.eat = function(){
        console.log("animal eat.");
    }
}

function Dog(){
    //构造函数继承
    Animal.call(this);
    this.bark = function(){
        console.log("dog bark.);
    }
}

//借助原型链继承
Dog.prototype = Animal.prototype;

Dog.prototype.constructor = Dog;


var dog = new Dog();

描述new一个对象的过程

 

 

function Mynew(Func){
    //创建一个对象,对象继承自Func.prototype
    var newObj = Object.create(Func.prototype);

    //执行Func()
    var result = Func(newObj);
    if(typeof result === "object"){
        return result;
    }else{
        return newObj;
    }
}

zepto(或其他框架)源码中如何使用原型

3.作用域和闭包

1. 变量提升

// 函数声明

//正常运行
fn();

//函数声明
function fn(){
	//
}

// 变量声明提前 var fn1 = undefined;
//undefined is not a function
fn1();
//函数表达式
var fn1 = function(){

}

2.执行上下文

 

3.this

this要在执行时才能确认,定义时无法确认;

4.作用域

JS没有块级作用域

只有函数和全局作用域

作用域是在定义时确定的

 

5.作用域链

自由变量

 

6.闭包

函数作为返回值(闭包使用场景)

//1.函数作为返回值

function F1(){
    var a = 100
    
    //返回一个函数,即函数作为返回值
    return function (){
        console.log(a);
    }
}


//  f1得到一个函数
var f1 = F1(); 
var a = 200; 

f1();//100

函数作为参数传递(闭包使用场景)

 

function F1(){
    var a = 100;    
    return function (){
        
        //自由变量,父作用域中寻找
        console.log(a);
    }
}

var f1 = F1();//返回一个函数

function F2(fn){
    var a = 200
    fn();
}

F2(f1);
//100
//注意:作用域是在定义的时候确定的!!!!!!

创建10ge<a>标签,点击的时候弹出来对应的序号 

var i
for(i = 0;i<10;i++){
    (function(){
        var a = document.createElement("a");
        a.innerHTML = i +"<br>";
        a.addEventListener("click",funcyion(e){
            e.preventDefault();
            
            //自由变量,要去父作用域获取值
            console.log(i);
        })
        document.body.appendChild(a);
    })(i);
}

 ⭐闭包实际应用中主要用于封装变量,收敛权限

function isFirstLoad(){
    var _list = [];
    return function(id){
        if(_list.indexOf(id)>=0){
            return false;
        }else{
            _list.push(id);
            return true;
        }
    }        
}


//使用
var firstLoad = isFirstLoad();

firstLoad(10);// true
firstLoad(10);// false
firstLoad(20);// true
firstLoad(30);// true
firstLoad(40);// true

//在函数的外面是不可能修改掉_list的值的

4.异步和单线程

 什么是异步(和同步对比)

 输出结果为:100 300 200

如果是同步,那么会阻塞程序进行,而异步不会阻塞

如果是同步,那么会先输出100,然后等1000ms输出200,等待输出后,才输出300

何时需要异步?

在可能发生等待的情况

等待过程中不能像alert一样阻塞程序运行

因此,所有等待的情况都需要异步

前端使用异步的场景

定时器:setTimeout和setInterval

网络请求ajax和动态img、script加载

console.log("start");

var img = document.createElement("img");

img.onload = function(){

console.log("loaded.")

}

img.src = "https://www.wangbase.com/blogimg/asset/201903/bg2019301803.jpg"

console.log("end");

//输出:start end loaded.
console.log("start")

$.get("./data1.json",function(data){

    console.log(data);

})

console.log("end.");

//输出 start end. 数据data的内容

事件绑定

console.log("start")

document.getElementById("btn1").addEventListener("click",function(data){

    console.log("clicked.");

})

console.log("end.");

//输出start end. clicked.

ES6中的Promise

异步和单线程

 

 

5.日期和match

日期毫秒数从1970年开始到现在的毫秒数

 

6.数组和对象的API

数组API

对象API

var obj = {
    x:100,
    y:200,
    z:300
}

var key 

for(key in obj){

    //注意这里的obj对象的hasOwnProperty()
    console.log(obj.hasOwnProperty(key));
    console.log(key);
    console.log(obj);

    if(obj.hasOwnProperty(key)){
        console.log(key,obj[key]);
    }
}

获取随机数,要求长度一致的字符串格式

var random = Math.random();

random+="0000000000"//后面加10个0

//
random.substring(0,10);
random.slice(0,10);
random.substr(0,10);



console.log("123456789012345678".substring(0,10));//"1234567890"
console.log("123456789012345678".slice(0,10));//"1234567890"
console.log("123456789012345678".substr(0,10));//"1234567890"

 写一个能遍历对象和数组的forEach函数

function MyEach(obj,fn){
    if(obj instanceof Array){
        obj.forEach(function(item,index){
            console.log(item);
            fn(item);
        })
    }else{
        for(var key in obj){
            //遍历对象可以使用Object.keys(),for...in...,
            console.log(key,obj[key]);
            fn(key,obj[key]);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值