Javascript相关知识

1、函数定义方式
function add1(num1,num2){
    return num1 + num2;
}

var add2 = function(num1,num2){
    return num1 + num2;
}

var add3 = new Function("num1","num2","return num1 + num2");

window.console.log("add1 = " + add1(10,20));
window.console.log("add2 = " + add2(100,200));
window.console.log("add3 = " + add3(1000,2000));
2、对象
var obj = new Object();
obj.name = "张三丰";
alert(obj.name)

var obj = Object();
obj.name="zhangsanfeng";
alert(obj.name);

var obj = {};
obj.name = "zhangjunbao";
alert(obj.name);

var obj = {
    name:"张三丰",
    age:28,
    add:function(num1,num2){
        return num1 + num2;
    }
};
alert(obj.name);
alert(obj['name']);// 以数组的方式来访问属性,必须有单引号或是双引号
alert(obj.add(10,20));
3、变量作用域和内存

在JavaScript中,基本数据类型(undefined,null,boolean,number,string)是存储在栈内存,其占据的空间是固定的;而引用类型(Object)是存储在堆内存,其占据的空间是要动态分配的,在栈内存中会保留有引用类型的一个地址,当访问这个引用类型的时候,先到栈空间找到该引用类型的地址,然后通过这个地址找到值;
基本数据类型是按值来访问的,引用数据类型是按引用访问的;JavaScript中数据都是按值来传递的。

QQ截图20160914100531.png
4、面向对象与原型

在第二节中列举了几种创建对象的方法,那些方法有个问题,就是如果有多个对象的情况下要进行重复实例化,如何解决这个问题,有一下几种方式:
工厂方法创建对象

function createObject(name,age){
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.description = function(){
        window.console.log(this.name + "," + this.age + ",来自中国......");
    }
    return obj;
}

var obj1 = createObject("Jackson",29);
var obj2 = createObject("黄飞鸿",129);
obj1.description();
obj2.description();

工厂方法创建对象解决了重复实例化的问题,但是又带来了新的问题:无法区分出到底是哪个对象的实例。

构造函数方式

/**
* 1、所有的构造函数其实就是Object;
* 2、构造函数没有new Object,但在后台会自动new Object();
* 3、this相当于var obj = new Object()中的obj;
* 4、构造函数不需要返回值
* --------------------构造函数规范-----------------------------
* 1、构造函数也是函数,但必须首字母大写;
* 2、必须new 构造函数创建对象
*/
function UserInfo(name,age){
    this.name = name;
    this.age = age;
    this.description = function(){
        window.console.log(this.name + "," + this.age + ",来自中国......");
    };
}

var user1 = new UserInfo("Hello",29);
var user2 = new UserInfo("word",20);
user1.description();
user2.description();

//--------------------------------------------------------

// 寄生构造函数 = 工厂模式 + 构造函数
// 稳妥构造函数:在构造函数中不能使用this,创建对象的时候不能使用new
function User(name,age){
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.description = function(){
        window.console.log(name + "," + age + ",来自中国......");
    }
    return obj;
}

var obj1 = User("Jackson",29);
obj1.description();

对象冒充

function UserInfo(name,age){
    this.name = name;
    this.age = age;
    this.description = function(){
        window.console.log(this.name + "," + this.age + ",来自中国......");
    };
}

var userReplace = new Object();
UserInfo.call(userReplace,"haha",39);
userReplace.description();

对象原型
上述创建对象的方式,解决了诸如重复实例化的问题、无法区分出到底是哪个对象的问题。但是,还是存在一个问题:对象中的方法占用内存问题!对于每个对象来说,其属性值是可变的,但是其方法基本是不变的,如果采用上述方式创建了对象的实例,那么每个实例中的每个方法都独自占据一定的内存,这样就浪费了大量的内存了,这个时候就可以使用对象原型了。在JavaScript中,每个对象都有原型对象,对象都继承原型对象的所有属性,基于这个原理,对于对象中的方法和常量,就可以使用原型来定义了。

function UserInfo(name,age){
    this.name = name;
    this.age = age;
}

UserInfo.prototype.description = function(){
    window.console.log(this.name + "," + this.age + ",来自中国......");
}

var user1 = new UserInfo("张三丰",200);
user1.description();
function UserInfo(name,age){
    this.name = name;
    this.age = age;

    if(typeof this.description != 'function') {
        window.console.log("开始。。。。。。。。。");
        UserInfo.prototype.description = function(){
            window.console.log(this.name + "," + this.age + ",来自中国......");
        }
        window.console.log("结束。。。。。。。。。");
    }   

}

var user1 = new UserInfo("张三丰",200);
user1.description();

var user2 = new UserInfo("张君宝",200);
user2.description();

继承
JavaScript中,所有的对象都有一个原型对象,所有的对象都继承原型对象的属性。
** 1)原型链继承 **

/////////////////原型链继承
function Human(){
    this.name = "张山峰";
}

function Man(){
    this.sex = "男";
}

// Man所有的对象都继承其原型对象,而Man的原型对象被指定为Human,这样就实现了继承了。
Man.prototype = new Human();

var man = new Man();
window.console.log(man.name + "," + man.sex);

这种继承有一个问题:无法传参给超类,方法不能共享(原型会被打断)。

** 2)借用构造函数实现继承 **

/////////////////借用构造函数
function Human(name){
    this.name = name;
}

function Man(name,sex){
    // 采用对象冒充方式传参
    Human.call(this,name);
    this.sex = sex;
}

var man = new Man("张三丰99","男");
window.console.log(man.name + "," + man.sex);

这种继承解决了向超类传参的问题,但是因为没有使用原型,则就无法实现方法等共享问题

** 3)组合继承 **

/////////////////组合继承
function Human(name){
    this.name = name;
}

Human.prototype.description = function(){
    window.console.log(this.name + ",我来自于中国......");
}

function Man(name,sex){
    // 采用对象冒充方式传参
    Human.call(this,name);
    this.sex = sex;
}
// Man的原型指向了Human
Man.prototype = new Human();
var man = new Man("张三丰88","男");
window.console.log(man.name + "," + man.sex);
man.description();

解决了向超类传参问题,使用了原型链,实现了方法共享。

** 4)原型式继承 **:不单独使用

// 临时中转函数
function transition(obj){
    function F(){};
    // 这里的F继承了obj
    F.prototype = obj;
    return new F();
}
// 字面量方式声明一个对象
var obj = {
    name : "zhangsanfeng",
    age : 100,
    arr:["aa","bb"]
};

var obj1 = transition(obj);
obj1.arr.push("cc");
window.console.log(obj1.arr);// ["aa", "bb", "cc"]

var obj2 = transition(obj);
// 共享带来的问题:没法独立持有自己的信息了
window.console.log(obj2.arr);// 是["aa", "bb", "cc"]而不是["aa", "bb"]

** 5)寄生式继承 **:原生式+工厂模式

// 临时中转函数
function transition(obj){
    function F(){};
    // 这里的F继承了obj
    F.prototype = obj;
    return new F();
}

// 寄生函数
function create(o){
    var f = transition(obj);
    return f;
}


// 字面量方式声明一个对象
var obj = {
    name : "zhangsanfeng",
    age : 100,
    arr:["aa","bb"]
};

var obj1 = create(obj);
obj1.arr.push("cc");
window.console.log(obj1.arr);

var obj2 = create(obj);
// 共享带来的问题:没法独立持有自己的信息了
window.console.log(obj2.arr);

** 6)寄生组合继承 **

// 临时中转函数
function transition(obj){
    function F(){};
    // 这里的F继承了obj
    F.prototype = obj;
    return new F();
}

// 寄生函数,子类的原型指向建立的中转对象,中转对象原型指向超类:原生链继承
function create(parent,child){
    var f = transition(parent.prototype);
    f.constructor = child; // 
    child.prototype = f; // child的原型指向了中转类
}


function Human(name){
    this.name = name;
}

Human.prototype.run = function(){
    window.console.log(this.name + "..............");
}

function Man(name,sex){
    // 对象冒充,实现参数传递
    Human.call(this,name);
    this.sex  = sex;
}

// 寄生组合继承
create(Human,Man);

var man = new Man("张三丰88","男");
man.run();
window.console.log(man.name + "," + man.sex);
5 匿名函数与闭包
// 匿名函数赋值给变量
var add = function(){
    window.console.log("hhhhhhhhhhhhhhhhhhh");
};
add();


// 自运行 (匿名函数)()
(function(name){
    window.console.log(name + "来自于中国。。。。。。。");
})("zhangsanfeng");

// 函数里面放置一个匿名函数
function userInfo (){
    return function(){ // 闭包:在一个函数中创建另外一个函数,通过另外一个函数访问这个函数的局部变量
        return "userInfo"
    }
}

window.console.log(userInfo()());

function increase(){
    var count = 0;
    return function(){
        count++;
        return count;
    }
}

window.console.log("count1 = " + increase()());
window.console.log("count2 = " + increase()());
window.console.log("count3 = " + increase()());
var f = increase();
// 闭包的优点也是缺点:闭包作用域里面的局部变量资源不会被立刻销毁,如果使用不当,会造成内存泄漏
window.console.log("count11 = " + f());
window.console.log("count12 = " + f());
window.console.log("count13 = " + f());

循环中的闭包

function arrCreate(){
    var arr = [];
    for(var i=0;i<5;i++){
        // 匿名函数自我执行
        arr[i] = (function(num){
            return num;
        })(i);
    }
    return arr;
}

var arr = arrCreate();
for(var i=0;i<5;i++){
    window.console.log("arr[" + i + "] = " + arr[i]);
}
//////////////////////////////////////////////////////
function arrCreate(){
    var arr = [];
    for(var i=0;i<5;i++){
        arr[i] = (function(num){
            // 局部变量驻留在内存中
            return function(){
                return num;
            };
        })(i);
    }
    return arr;
}

var arr = arrCreate();
for(var i=0;i<5;i++){
    window.console.log("arr[" + i + "] = " + arr[i]());
}

闭包引起的内存泄漏问题:

window.onload = function test(){
    var testDiv = document.getElementById("testDiv");
    testDiv.onclick = function(){
        // 这里的testDiv将驻留在内存中,得不到及时的释放,将会引起内存泄漏
        window.console.log("hhh-->" + testDiv.innerHTML);
    }
};

模仿块级作用域

(function test () {
    for (var i = 0; i < 5; i++) {
        
    }
    // 因为JavaScript中并没有块级作用域这种概念,所以这里的i是还能访问到的
        // 即使这里再次声明了i,比如var i;也是没有作用的
    window.console.log("i = " + i);
})();

(function test () {
    (function(){ // 闭包模仿块级作用域
        for (var i = 0; i < 5; i++) {
            window.console.log("i = " + i);
        }
    })();
    // 这里就访问不到i了
    window.console.log("i = " + i);
})();

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

推荐阅读更多精彩内容

  • 第十章 变量、作用域及内存 JavaScript的变量与其他语言的变量有很大区别。JavaScript变量是...
    上书房_张强阅读 420评论 0 2
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,605评论 18 399
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,405评论 3 12
  • 这些天一直有种空虚感,就是每天计划要学习和成长自己的内容被每天的琐事或者是主观上并没有主动的争取更多的时间去成...
    史真如阅读 97评论 0 0
  • 需要注意: 重命名表的SQL格式为ALTER TABLE RENAME TO; 导入新数据的insert into...
    Ten_Minutes阅读 293评论 0 1