看透JS学习笔记

JS是一种事件驱动型语言, 只有当浏览器要执行事件时才会执行JS代码。

浏览器产生事件之后,JS的事件管理器会先到事件队列中查找与此类事件相关的处理方法(即绑定了相应事件的函数), 如果存在,则会执行绑定了相应事件的JS代码(函数), 如果没有找到一个函数绑定了相应事件,则会丢弃这次事件的请求

JS的属性:

JS的属性分为两种类型, 一种是基础类型, 一种是对象类型

对象属性又分为object对象和function对象

基础类型的属性不能再包含属性

对象类型的属性可以再包含自己的属性

JS内存模型:

在内存中,直接量通过两块内存分别保存属性名和属性值

对象需要三块内存,  分别保存属性名、属性地址和   属性内容     即     属性名指向属性对应的地址, 而该属性存储在另一块空间中

 

function类型和function对象

创建function:

创建function有两种方式:

①函数声明:

function 函数名 (形参) {函数体}

②函数表达式:

var 变量名 = function (参数列表) {函数体}       省去了函数名, 但是前面用一个变量保存函数对象的地址

 

两种创建函数方式的关系:

在JS中所有的数据只有两种形式,要么是对象的属性, 要么是变量。

无论是对象的属性还是变量, 在内存中都是名值对的结构

因为函数是对象, 所以也应该是名值对的结构

通过声明方式创建函数时, JS首先创建了函数对象, 然后又创建了和函数名同名的变量, 并将创建出来的函数赋值给了这个变量

 

函数本身也是对象:

JS中的函数本身也是对象, 那么就可以有自己的属性, 函数的属性一般是使用点操作符来操作的, 可以通过点来给对象的属性进行赋值, 如果属性不存在则会直接创建该属性, 如果存在, 则可以对其中的内容进行修改

函数的属性可以是直接量, object对象和 function对象中的任意一种, 如果function对象类型的属性, 还可以通过点操作符来调用,示例代码如下:

function Func () {

 }

Func.val = "I am Func";
a = "a";
a = "b";

Func.logVal = function(){
    console.log(this.val);
}

Func.logVal();

进入strict模式:

可以在文件或者函数内部使用"use strict" 字符串进入严格模式, 推荐以function级的严格模式, 因为可能有时会用到其他人的代码

调用子函数和嵌套函数中查找变量的区别:

使用嵌套函数,变量会从作用域链的上部往下依次找, 即从内层往外层依次找

调用子函数不会使用主调函数中的变量

var v = 0;  //定义全局变量
function logV() {
    console.log(v);  //这里因为函数内部没有定义变量v, 所以会使用全局的v, 但是不会使用其他函数中的值
                        //因为他们并不是存放在一块内存区域,他们不在一个作用域链中
}

function f (){
    var v = 1;   //定义函数内部变量是v, 作用域是function 级
    logV();  //调用子函数
}

闭包:

在JS中, 函数就是一块保存了现有数据的内存, 只要找到这块内存就可以对其进行调用。 想办法获取内部定义的嵌套函数,就可以在外部使用嵌套函数来调用内部的局部变量, 这种用法就是闭包。

function f1 (){
    var v = 1;
    function f2(){
        console.log(v);
    }
    return f2;
}

var f = f1();  //通过调用外层函数来获取内部的嵌套函数对象的地址, 然后赋值给f, 这样f就指向了这块空间, 则可以通过f调用内层函数
                    //进而使用内部的局部变量 v;
f();

在使用闭包时, 在保存返回函数的变量失效之前定义闭包的function 会一直保存在内存中

 

当function的函数体返回一个对象类型时, 使用new关键字创建的对象就是返回的对象 而不是function所对应的对象

function F(){}
function Car (color, displacement){
    this.color = color;
    this.displacement =displacement;
    return new F();   //此时返回的是通过new创建的F函数类型的对象,而不是这个F函数对象
}

var car = new Car("black", "2.4T");  //因为构造函数Car中最后返回了  F类型的对象, 所以car指向的是那个新建的F函数对象类型的类型的对象
console.log(car.color + ", "+ car.displacement);    //undefined, undefined;
console.log(car instanceof Car);            //false;
console.log(car instanceof F);      //true;

 

prototype 注意事项:

prototype 可以实现继承和多层继承

function log(msg){   //创建一个名称为log 的函数对象
    console.log(msg);
}

function Person(){}   //创建一个名称为 Person 的函数对象
Person.prototype.logPerson = function(){  //给函数对象Person 的 prototype属性添加一个名称为 logPerson的function对象类型的属性
    log("Person");   //调用子函数log
}

function Teacher() {    //创建一个名称为Teacher的function对象
    this.logTeacher = function(){      //给通过Teacher创建出来的对象创建  名称为logTeacher的 function对象类型的属性
        log("teacher");  //调用子函数log
    }
}

Teacher.prototype = new Person();   //让Teacher 的 prototype属性指向  一个  Person函数对象类型的对象
Teacher.prototype.logPrototype = function(){   //给Teacher的prototype属性再添加一个 logPrototype  属性
    log("Prototype");    //调用子函数log
}

var teacher = new Teacher();   //创建Teacher 函数对象类型的对象teacher
teacher.logTeacher();   // 先查看自己是否有这个属性, 有, 则调用自己的属性
teacher.logPrototype(); //   先查看自己是否有这个属性, 没有, 则到 Teacher 的prototype 属性中查找是否有这个属性, 有, 则调用
                                    //Teacher 的 prototype属性的logPrototype属性

teacher.logPerson();
//先查看自己是否有这个属性, 没有, 则到 Teacher的 prototype属性中查找是否有这个属性, 没有, 
//因为Teacher的prototype属性指向了一个 Person函数对象类型的对象, 所以会到Person 的prototype属性中查找是否有这个属性, 有
//则调用Person 的 prototype属性的 logPerson属性

prototype 是属于 function 类型对象的属性

function 类型对象的 prototype 属性是 object 类型的对象

一:

function 类型对象的 prototype 属性对象的属性 可以被 function 类型对象所创建的 object类型的实例对象使用,
但是object类型的实例对象自身并没有prototype 属性

 

二:

如果要给 function 对象的 prototype 属性赋予新的值并且又要添加新的属性, 则应该先赋予新的值, 再添加属性。
否则再赋值时, 会出现找不到给赋值之前的 prototype 对象, 进而就找不到之前添加的属性

 

总结:
    function创建的对象在调用属性时, 是按照prototype 链依次查找的, 而不是将 prototype中的属性关联到创建的对象本身,
    因此创建完对象后, 再修改function 的 prototype 也会影响到创建的对象的调用

    prototype 中的属性是动态查询的。
    prototype除了可以实现继承外, 还可以节约内存, 因为无论使用function 创建多少对象, 他们所指向的prototype 对象在内存中都只有一份
    但是prototype 中的属性比直接使用对象中定义的属性在执行效率上要低一些

 

object类型对象:

创建 object类型对象的三种方法:

①:通过花括号创建

var obj = {
     v:6,                 
     innerObj: { 
         v: 7
     },
     logV: function(){
         console.log(this.v);
     }
 }

 console.log(obj.v);    //6
 console.log(obj.innerObj.v);    //7
 console.log(obj.logV);     //6

②: 使用function类型对象 创建:

function F(){
    this.name = "liu";
}

var obj = new F();   //通过函数对象来创建 object对象
console.log(obj.name);

3: 通过 Object.create 方法创建

var obj = Object.create(
    //prototype参数是一个 object 类型的对象, 所以可以用花括号创建
    {
        type: "by create"
    },  //调用函数时,多个参数用逗号隔开

    //propertiesObject参数也是一个 object类型对象, 也可以用花括号创建
    {
        color: {            //创建color属性
            value: "red",
            enumerable: true
        },      //花括号创建对象时多个属性用逗号隔开

        size: {
            value: "37",
            enumerable: true
        }
    }

);

//该obj对象自身只有两个属性  color 和 size
console.log(obj.type);   //"by create"  现在当前 object类型对象中找该属性, 没有, 则会去 prototype 属性对象的属性中去找
console.log(obj.color);     //red;
console.log(obj.size);  //37;
console.log(Object.getOwnPropertyNames(obj));// 获取obj自己拥有的属性  //Array(2) ["color", "size"]

调用 object对象属性的两种方法:

1, 直接通过点操作符调用

2, 通过方括号调用, 当要调用的属性名是一个变量时, 只能由方括号调用

 

注意点:

对于用花括号和function对象创建的对象, 都可以直接调用 Object 的 prototype 属性对象的属性

但是对于用 Object.create 属性创建的对象, 如果第一个 prototype 参数传递的是null, 则创建出的对象不能直接调用Object 的prototype 属性对象的属性

使用花括号创建的对象, 其constructor指向的是Object 函数对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值