JavaScript高级

JavaScript高级

数据类型

在JS中 字符串不只是字符串 还是一个对象

string类型
var str = 'xxxxxx';//一般声明方式
var str2 = new String('yyyyyy');//底层原型声明方式->对象

array类型(typeof为object) //万物皆对象(函数)
var arr = [1,2,3];//一般声明方式
var arr2 = new Array();//底层原型声明方式->对象

object类型
var obj = {};//一般声明方式
var arr2 = new Object();//底层原型声明方式->对象

构造函数(本质为自定义函数)

区别:构造函数与自定义函数唯一没有意义的区别为构造函数命名方式采用大驼峰

作用:一般用来构建对象(通过new关键字实例化)如 new String() new Array()

//构造函数
function Xiaohuwei(){
    console.log('Hello world');
}
//自定义new一个女朋友对象
function Grilfriend(){
    console.log('memeda');
}
//实例化
var gf = new Grilfriend();

判断是否为真数组

var arr = [1,2,3];
通过instance关键字判断//instanceof判断原型对象是否一致(是否在一条原型链上)
console.log(arr instanceof Array);//返回值为布尔
数组可以为数组或者对象 但是对象不能为数组

再分类

数组和对象统一为为引用类型


作用域问题

var str = 'xxxxxx';//全局(顶级)->所有区域都可使用
function memeda(){
    var str2 = "yyyyy";//二级变量 作用域在memeda内部
    console.log(str);
    function heheda(){
        console.log(str);
        console.log(str2);
    }
    heheda();
    console.log(str2);
}
memeda();
作用域链:作用域的生效区间由外到内延申 形成的作用域区间

函数闭包

也就是内嵌函数

function son(){
    var num = 1;//二级变量初始值
    function getNum(){
        num++;
        return num;//将num的值反出去
    }
    return getNum;//将内部嵌套的函数反出去
}
var getnums = son();//代理到了内部嵌套函数
console.log(getnums());//第一次 2 
console.log(getnums());//第二次 3 
console.log(getnums());//第三次 4 
var num = getnums()//第四次 5
console.log(num)//5
num = null //手动销毁(置空)
console.log(getnums());//第五次 null 
普通变量:用完被GC回收 
闭包后的变量:保存在内存中 不被销毁 可以动态获取到局部变量的值

过多的使用闭包会导致内存泄露,可以手动销毁(避免内存泄漏)也就是手动置空

自调函数

var pras = "tom";
(function(val){
    console.log('hello'+val);
})(pras)
永远自动执行一次 在闭包可以被完美解析

闭包和自调函数应用场景

已知页面有诺干个li标签 点击每一个弹出相应的下标

for(var i = 0; i<lilist.length;i++){
    (function(){//自调函数
        var id = i;//将i重新赋值给id 保存当前i的值 之后与i无关
        lilist[i].onclick=function(){
            alert(id);//弹出上面保存过的i的值
        }
    })()
}
es6 可以用let声明解决

变量提升

在js中 变量的声明是最优先的 赋值之类的操作按照正常程序从上至下

var没有块级作用域 可以变量提升 let有块级作用域 不存在提升

变量在使用过程中会使用就近原则
var memeda = 'xxxxxxx';
function heheda(){
    console.log(memeda);//打印underifend  因为它最近作用域在函数内部 而函数内部只申明了还没有赋值
    var memeda = '100';
    console.log(memeda)
}

JS面向对象

本质就是构造函数

 对象字面量
 var obj = {};
//创建对象 封装构建函数 不能直接调用!需要通过new关键字
function User(userName,sex){
    this.userName = userName;
    this.sex = sex;
    this.dosomething = function(){
        console.log('i can singing....');
    }
}
//调用
var stu = new User('么么哒','女');
console.log(stu.userName);
prototype 显示原型 只有构造函数才具有 也是一个对象 具有隐式原型
_proto_ 隐式原型 只有对象才具有
constructor 所有对象都具备该属性 指向构造函数

一个对象的 __proto__ 指向其构造函数的 ptototypeUser().__proto__ == User.prototype

有了显示原型才有隐式原型

所有的隐式原型都不可用 ,一般用到的方法都是在用底层构造函数的显示原型,因为隐式原型继承的是构造函数的显示原型。所有对象的构造函数(原型)都是 Object() object的父构造函数为空。

继承 Extends

将一些对象公有的属性和方法挑选出来放到一个父原型里面

原型链直接继承

人类
function Person(){

}
    Person.prototype.man = '男';
    Person.prototype.women = '女';
    Person.prototype.eat = function(){
        console.log("i can eat ...");
    }
    Lower.prototype = Person.prototype//原型链直接继承
    Lower.prototype.constructor = Lower//解决继承链紊乱问题
程序员
function Lower(){
    this.writeBug = function(){
        console.log('i can just bug...')
    }
}
var obj = new Lower();//会导致继承链紊乱
console.log(obj);

直接继承

公有手机原型
function Phone(color){
    this.color=color;
    this.playgame=function(){
        console.log("i can playgames");
    }
}
Huaweipro30.prototype = new Phone("black");//将华为的原型指向手机公有的原型 既继承 
华为手机
function Huaweipro30(color){
    this.color=color;
    this.hwx = function(){
        console.log("hwx....");
    }
}
//原型直接继承
var hw = new Huaweipro30();//会导致继承链紊乱
Huaweipro30.prototype.constructor = Huaweipro30;//解决继承链紊乱问题
console.log(hw.color);//black

继承链紊乱

使用上述实例化后 hw对象的构造函数指向Phone() 而不是指向Huaweipro30() 解决办法如上

注意

数组和对象属于引用类型不会重新开辟内存,如果用一个构造函数实例化了两个对象A 和B ,并且继承方式采用上面任何一种,如果在对象A中改变了构造函数的数组或者对象,那么改了之后相应的数组或者对象在对象B中也会生效,如果对象A修改了构造函数的属性(字符串)会重新开辟内存,则不会影响对象B,只对A生效。解决办法就是改变继承方式,使用构造函数绑定解决。

构造函数绑定 Call 和 Apply

所有函数的构造方法(原型)为 Function 而该函数里面具有 call()apply() 方法

注意:这两种方法只有构造函数具有

作用:将一个构造函数的实例对象赋值给另一个对象(对象复制)

一个参数实例

function User(){
    this.userName = "张三";
    this.doing = function(){
        console.log('i can liaomei...');
    }
}
function Memeda(){
    
}
var obj = new Memeda();//用Memeda实例化
User.call(obj)//将User对象的属性和方法复制给了obj
或者
User.apply(obj)
console.log(obj.userName)//张三

或者

function User(){
    this.userName = "张三";
    this.doing = function(){
        console.log('i can liaomei...');
    }
}
function Memeda(){
    //构造函数绑定继承
    User.call(this);
}
var obj = new Memeda(); 
console.log(obj.userName)//张三

两个参数实例->传参问题

function User(userName,sex){
    this.userName = userName;
    this.sex = sex;
    this.doing = function(){
        console.log('i can liaomei...');
    }
}
function Memeda(userName,sex){
    //构造函数绑定继承
    User.call(this,userName,sex);//参数传递匹配
    或者
    User.apply(this,[userName,sex]);
}
var obj = new Memeda('张三','女'); 
console.log(obj.userName)//张三
console.log(obj.sex)//女

call()apply()的区别在构造函数实例化过程中参数传递绑定的方式不一样,如上代码块, 前者需要一行写完,后者只需要一个数组即可。


ES6面向对象

语法糖🍬

class类的内部 只能出现方法

class User{
    //声明属性->魔术方法 当User类被实例化时直接自动调用 
    constructor(userName,sex){//固定名字
        this.userName = userName;
        this.sex = sex;
        this.doing();//实例化下面的doing方法
    }
    //声明方法
    doing(){
        console.log('...xxx...');
    }
}
var obj = new User('么么哒','男');
//调用方法
obj.doing();//...xxx...
//调用属性
obj.userName;//么么哒
obj.sex;//男

ES6继承

父
class Phone{
    constructor(color,type){
        this.color = color;
        this.type = type;
    }
    callNum(){
        console.log("i can call....")
    }
}
子
class Hw extends Phone{ //通过extends关键字继承
    constructor(size,color,type){
    super(color,type);//必须使用super关键字子级和父级的继承关系才正常 这样就会把两级的构造函数合并
        this.size = size;
    }
    hwx(){
        console.log("i can position...");
    }
}
var obj = new Hw("p30",'red','iphone');
obj.callNum();//i can call....
obj.type;//iphone
obj.color;//red

当子函数没有构造函数的时候会驱动父级的构造函数,es6继承时需要使用super()方法关联 参数位置写父构造函数的参数。

类的特征

!!!
<font color=red size=4>1.封装 2.继承 3.多态</font>
!!!

PHP构造函数

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

推荐阅读更多精彩内容