JavaScript 基础

[toc]

  1. 省略了部分基础内容, 来自腾讯课堂渡一教育
  2. 章节
    1. 变量, 值类型, 运算符
      1. 声明变量
      var a=2,
          b=3,
          c;
      
      1. 分类
        1. 原始值: Number, Boolean, String, undefined, null.
          存储在栈中.
        var a = 10;
        b = a;
        a = 20;
        console.log(b)
        //输出10
        
        1. 引用值: Array, Object, function.. date ReExp.
          存储在堆中
      ```
      var a = [1,2];
      b = a;
      a.push(3);
      console.log(b);
      //输出[1,2,3]
      a = [1,3];
      console.log(b);
      //输出[1,2,3]
      ```
      
    2. 运算符
      1. '+'
        1. 数学运算和字符拼接.
        2. 任何数据类型和字符串相加为字符串
      2. '* / - %'
        1.  1/0 //infinite
           -1/0//-infinite
           0/0//NaN
          
      3. 比较运算符, 结果布尔值
        1. 字符串比较ascii码
        2.  NaN == NaN //false
          
        3. &&和||:返回结果根据前后的表达式是否为真, 返回表达式的值
          表达式结果 undefined, null, NaN, '', 0 , false转换为false
        2 && 3+1//相当于if语句
        
    3. typeof , 类型转换
      1. typeof

        1. Number, String, undefined, object, function
        2. 返回的值是字符串
        3. 未声明的变量返回的是undefined, 不会报错
      2. 显示类型转换

        1. Number()
        ```
         Number(true)//1
         Number(null)//0
         Number(undefined)//NaN
         ```
        
        1. parseInt()
        parseInt(true)//NaN
        

parseInt(12.9)//12
parseInt(10, 16)//16, 以第二个参数为基底转换成10进制
```

  • parseFloat()
  • String()
  • Boolean()
  • toString()
    • undefined, null不能用toString()
    • toString(<radix>)把10进制数字转化为目标进制
//2进制转换为16进制
var num = 101010;
var test = parseInt(num, 2);
test.toString(16);

2.3.4 隐式类型转换

  • isNaN()
    调用Number()
  • ++/-- +/-(一元正负)
    调用Number()
  • '+'
    如果有字符串, 调用String()
  • */%-
    调用Number()
  • && || !
  • < > <= >=
    有数字调用Number()
  • == !=
    有数字会调用Number()
var str = false + 1; //str是1
var demo = false == 1;//false
if(typeof(a)&&-true +(+undefined) +''){
}//undefined&&'NaN', 为true
if(11 + '11' * 2 == 33){}//if为true
!!' ' + !!'' - !!false //为1
typeof(null)//object

2.4 函数, 初始作用域
2.4.1 函数

  • 定义
funtion test(){};
//匿名函数表达式
var test = function(){};
test.name //test
(window.foo || (window.foo = 'bar'));//(window.foo = 'bar')括号有优先级, 先赋值
  • 参数
    形参和实参个数可以不一致
function test(){
  console.log(arguments.length)//实参长度, arguments实参列表, 映射关系, 其中元素和实参不是同一对象
  console.log(test.length)//形参长度
}

2.5 预编译
2.5.1 函数声明, 变量声明提升
2.5.2 暗示性声明变量(imply global):会将变量变为全局对象所有

function test(){
  var a=b=123//暗示性声明, 先将123赋值给b, b为全局所有
}

2.5.3 预编译步骤(在函数执行前一刻)

  • 创建一个AO对象, 执行期上下文
  • 找形参和变量声明, 作为AO对象的属性名, 值为undefined
  • 将实参和形参相统一
  • 找函数体的函数声明, 值赋予函数体
//试题1
function fn(a){
  console.log(a);//function a(){}
  var a =123;
  console.log(a);//123
  function a(){};
  console.log(a);//123
  var b = function(){};
  console.log(b);//function(){}
  function d(){}
}
fn(1)
// 1. AO
/*2. AO{
  a: function a(){},
  b: undefined,
  d: function(){} 
}未执行前的AO*/
//试题2
a = 100;
funtion demo(e){
  funciton e(){}
  arguments[0] = 2;
  console.log(e);//2
  if(a) {
      var b = 123;
      function c(){}//现在语法不允许if中声明函数
  }
  var c;
  a = 10;
  var a;
  console.log(b);//undefined
  f = 123;
  console.log(c);//function c(){}, 实际为undefined
  console.log(a);//10
}
var a;
demo(1);
console.log(a);//100
console.log(f);//123
/*GO{
  a:undefind,
  demo: function demo(e){},
  f: undefind,
}
AO{
  e:function e(){},
  b: undefind,
  c: function c(){},
  a: undefind
}demo未执行前*/
//试题
var x = 1, y = z = 0;
function  add (n) {
  return n = n +1;
}
y = add(x);
function add (n) { 
  return  n = n + 3;
}
z = add(x);
//x y z 考察预编译环节
//1 4 4

2.6
2.7 作用域 作用域链 立即执行函数
2.7.1 [[scope]]: 每个js函数都是一个对象, 对象中有些属性仅供引擎存取.[[scope]]就是其中之一, 里面有运行期上下文集合
2.7.2 运行期上下文: 当函数执行时, 会创建一个执行期上下文的内部对象. 一个执行期上下文定义了一个函数执行时的环境, 函数每次执行时对应的上下文都是独一无二的.
2.7.3 作用域链: [[scope]]里的集合成链式连接, 我们称其为作用域链
2.7.4 查找变量: 从作用域链的顶端依次向下查找

//示例函数和作用域链
function a () {
  function b () {}
  var a = 123;
  b();
}
var glob = 100;
a();

a函数作用域链.png

2.7.5 闭包
2.7.5.1 示例

function a () {
  function b(){
    var bbb = 234;
    console.log(aaa);
  }
  var aaa = 123;
  return b;
}
var glob = 100;
var demo = a();
demo();
闭包示例.png
  • 定义: 当内部函数被保存到外部时, 将会生成闭包.闭包会导致原有作用域不释放, 造成内存泄漏(内存占用不释放, 看起来能用的内存变少)
  • 作用:实现公有变量;可以做缓存(存储结构);可以实现封装, 属性私有化;模块化开发, 防止污染全局变量
//公有变量示例
function add () {
  var count = 0;
  function b () {
    count ++;
    console.log(count)  
  }
  return b;
}

2.7.6 立即执行函数

  • 定义: 此类函数没有生命, 在一次执行后立即释放, 适合做初始化工作.
  • 形式
(function () {} ())
  • 来自: (只有)表达式可以被执行符号执行
+ function test(){
    console.log('ass')
}()
//或者
var test = function test(){}()
//如果去掉+, 则报错. 因为运算符将其变成表达式
//()同样也是一个运算符
//下面有一个变形
function (a, b){console.log(a+b)}(1,2);
//不会报错, 上面一行会被视作两行, 不加实参报语法错误
  • 运用
function test(){
    arr = [];
    for(var i=1;i<10;i++){
        arr[i] = function (){
            console.log(i)
        }
    };
    return arr;
}
var myarr = test()
for(var j=1;j<10;j++){
    myarr[j]()
}
//输出9个10, 这是个闭包问题, function定义的时候没有马上执行, 当循环完毕后, test中的AO中i是10
//上面的解决办法
funtion test(){
    arr = [];
    for (var i=1; i<10; i++){
        function (j){
            arr[j] = function(){
                console.log(i)
            }(i);//添加个立即执行函数, 将i转为j变量. 相当于加个中间层的AO, 这个AO在函数test执行的时候同时执行, 并保存下i
        };
    };
    return arr;
}
//li加一个点击事件, 打印相应的索引
function test () {
  var liCollection = document.getElementByTagName('li');
   for( var i = 0; i < liColletion.length; i++){
    (function (j) {
      liColletion[j].onclick = function () {
        console.log(j);
      }//外部函数, 注意闭包
     }(i))
  }
}
var f = (
  function f () {
    return '1';
  },
  function g () {
    return 2;
  }
)();
typeof f;//number
var x = 1;
if (function test(){}){
    x += typeof test
}
console.log(x)//输出1undefined
//if语句的()使function test(){}变成一个表达式,返回一个function test()结果为真
//定义一个函数, 直接用函数名是undefined, 需要将其赋值到一个变量

2.8 对象 包装类
2.8.1 对象:是一种基础的变量类型
2.8.2 增删改查:

delete obj.name//不存在的属性返回为true
obj.name//访问不存在的属性为undefined

2.8.3 创建方法:

//1
var obj = {}//对象字面量/对象直接量
//2.构造函数
//系统自带的构造函数 Object Array Number
var obj = new Object();//相当于var  obj = {};
//自定义

2.8.4 构造函数内部原理(与函数的区别)

  • 在函数体最前面生成一个this对象 var this = {}
  • 执行this.xxx = xxx
  • 在函数的最后隐式的return this
    如果显示的返回原始值, 则会被系统忽略该句
    2.8.5 包装类
var num = new Number(123);
//num 是一个数字对象, 参与运算后变成数字
//可以添加属性
var str = new String('ab')

原始值不能有属性

var num = 4;
num.len = 3;
//new Number(4).len = 3 delete
//new Number(4).len undefinde delete
console.log(num.len);//undefinde
var str = 'abcd';
str.length = 2;
console.log(str.length)//4, 系统自带, 似乎不能改

2.9 原型链 call/apply
2.9.1 原型

  • 定义: 原型是function对象的一个属性, 他定义构造函数制造出的对象的公共祖先. 通过该构造函数产生的对象, 可以继承该原型的属性和方法.
  • 对象隐式属性:__proto__
    -对象查看构造函数: constructor
Person.prototype.name = 'sunny';
function Person (){
  //var this  = {__proto__ : Person.prototype}
}
var person = new Person();
Person.prototype = {
  name : 'cherry'
}
console.log(person.name)//输出sunny
//同下
/* var obj = {name: 'a'};
var obj1 = obj;
obj = {name:'b'}
*/
  • 创建对象另一种方法:
var obj = Object.create(<原型>)
var obj = Object.create(null)//不继承自Object.prototype
//手动加上__proto__系统不会承认
123.toString();//.会被识别为小数点
0.14 * 100//计算精度位小数点前后16位

2.9.2 call/apply
test() --> test.call()
call和apply第一个参数(对象)改变this的指向, 不同是的两者的传参不一样.apply传递参数的是数组
2.10 继承模式 命名空间 对象枚举
2.10.1 继承模式之一

function inherit(Target, Origin){
    Function F(){};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constructor = Target;//不加的话会指向Origin,  构造对象的constructor继承原型
    Target.prototype.uber = Origin.prototype
}

2.10.2 命名空间:变量放在对象里;闭包
2.10.3 属性遍历

var obj = {
    __proto__:{
    lastName:'ha'
    },
    prop: 123,//obj.name --> obj['name']
}

for(var prop in obj){
    console.log(prop)
    console.log(obj[prop])//写成obj.prop错误
    //会打印'ha', 系统的__proto__不会打印, 自己设的会打印 object.prototype.name = 'ha'
    //如果不想打印__proto__, 用hasOwnPorperty
}
//'height' in obj比hasOwnProperty范围大

2.10.4 instanceof

A instanceof B //A的原型链是否有B的原型

2.11 this
2.11.1 this分析

  • 函数预编译过程中this --> windnow
  • 全局作用域中的this --> window
  • call/apply会改变this的指向
  • obj.func(), 谁调用func指向谁
var name = '111'
var a = {
    name:'222',
    say: function(){
        console.log(this.name)
    }
}
var fun = a.say
fun()//111, 变成全局环境了
a.say()//222
var b = {
    name : '333',
    say: function(fun){
        fun()
    }
}
b.say = a.say
b.say()//333, 只是方法的引用
b.say(a.say)//111
//this, 笔试真题讲解下
var foo = 123;
function print () {
  this.foo = 234;
  console.log(foo);
}
print();//234分清this的指向
new print();//123
// 运行test() 和new test()的结果分别是?
var a = 5;
function test () {
  a = 0;
  alert(a);// 0 0
  alert(this.a);// 5 undefined
  var a;
  alert(a);//0 0
}

2.12 克隆
2.12.1 深克隆

function deepClone (origin, target) {
    var target = target || {},
        toStr = Object.prototype.toString,
        arrStr = '[object Array]',
    for (var prop in origin){
      if (origin.hasOwnProperty(prop)){
        if(type0f(origin[prop]) == 'object' && origin[prop] !== 'null') {
          if(toStr.call(originp[prop]) == arrStr){
            target[prop] = [];
          } else{
            target[prop] = {};
          }
          deepClone(origin[prop], target[prop]);
        }else{
          target[prop] = origin[prop];
      }
    }
}          

2.12.2 数组

  • 索引可以越界, 没有-1位
var arr = new Array(10)//如果只有一位参数, 将被作为长度为10的空数组
  • 数组方法
    • 改变原数组
      • push, pop, shift, unshift(-->push), sort, reverse
      • splice
//push方法实现
Array.prototype.push = function(){
  for(var i = 0; i < arguments.length; i++){
    this[this.length] = arguments[i]//this.length是调用该方法的数组对象
  }
  return this.length
}
//数组方法有负一位
//负数位实现
function (pos) {
  pos += pos>0?0:this.length;
}
//sort本身是比较ASCII码排序
//必须有来个形参
//返回值为负, 前面的数放在前面, 为0不动, 为正后面的数在前面
arr.sort(function (a, b){
  return  a-b//升序
});
  • 不改变原数组
    • concat, join --> split, toString, slice

2.12.3 类数组

  • 属性必须是索引(数字)属性, 必须要有length
var obj = {
    "0":'a',
    "1":'b',
    "length":2,//和属性索引具有联动性
    "push":Array.prototype.push,
    "splice":Array.prototype.splice//加了之后控制台会打印成数组形式[]
}
  • 属性可配置和不可配置性
    var num =123;
    一旦经历了var的参考做, 所得出的属性是不可配置属性, delete不掉
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,145评论 0 13
  • JavaScript学习(1)之JavaScript基础 由于工作原因,开发语言逐渐以JavaScript为主,所...
    AlphaGL阅读 419评论 0 2
  • 语法基础 - 词法 字符集 Unicode字符集, 区分大小写 注释 // /* */ 直接量 数字 小数 字符串...
    KeKeMars阅读 877评论 1 11
  • 向南小姐阅读 131评论 0 4
  • 曾经当我爱着别人时,你陪伴着我,给我男朋友不在身边所给不了的温暖,我不拒绝,我享受着,享受着那本不属于自己该得到的...
    焦虑重症患者阅读 120评论 0 0