js高级学习笔记(一)

面向对象、创建对象、原型….

(注:部分内容是来自所学视频里的内容)

面向对象的三大特性

一、封装

举个小例子来说明封装的必要性、
(1)在没有面向对象封装前我们是这样写代码的

var divs = document.getElementsByTagName( 'div' );

for(var i = 0; i < divs.length; i++) {

    divs[i].style.border = "1px dotted black";

}

然而,当你要获取其它的标签或是遍历获取到的标签,你就会重复上面的代码,当然也有几个单词不一样的啦,但是你不觉得你在做无用功吗?而且让你的代码看上去很冗余繁杂,你的工作伙伴也不愿意和你合作哒。So,有了面向对象的思想进行封装就好办了,下面请看这段代码….

var itcast = { 
    //获取元素模块
    getEle: { 
        tag: function (tagName) { 
            return document.getElementsByTagName(tagName); 
        }, 
        id: function (idName) { 
            return document.getElementById(idName); 
        } 
    }, 
    //设置css模块   
    setCss: { 
        setStyle: function (arr) { 
            for(var i = 0; i < arr.length; i++) { 
                arr[i].style.border = "1px solid #abc"; 
            } 
        }, 
        css: function() {}, 
        addClass: function() {}, 
        removeClass: function() {} 
        // ... 
    } 

};

var divs = itcast.getEle.tag(div);
itcast.setCss.setStyle(divs);

这样看起来是不是简单明了了很多,也不会有重复的代码。

二、继承

JavaScript当中继承是指一个对象没有一些属性和方法,把另外有一个对象的属性和方法,拿过来自己用。

(1)混入式继承 for in

var obj = {};
var obj1= {
    name : "继承",
    sayHello: function() {

        console.log("你好,我是继承");
    }
}

for(var k in obj1){
    //obj1[k]可以获取到对象的每一个属性
    //这里使用k给对象新增属性的时候不可以使用点语法
    obj[k]=obj1[k];
}
console.log(obj);

(2)原型继承(利用共享)

//(1)给原型对象添加新成员
function Person(name,age) {
    this.name=name;
    this.age=age;
}
Person.prototype.sayHello=function(){
    alert(this.name+"你好");
}
var p=new Person("GJ", 18);
p.sayHello();

//(2)直接替换原型对象
function Person(name,age) {
    this.name=name;
    this.age=age;
}
var sister={
    sayHello : function(){
        alert(this.name+"你好");
    }
}
Person.prototype=sister;
var p=new Person("GJ", 18);
p.sayHello();

//(3)利用混入的方式给原型对象添加成员
function Person(name,age) {
    this.name=name;
    this.age=age;
}
var sister={
    sayHello : function(){
        alert(this.name+"你好");
    }
}

for(var i in sister){
    Person.prototype[i]=sister[i];
}
var p=new Person("GJ", 18);
p.sayHello();
//注意:这种方式很可能把原型中的原有的对象给替换掉

(3)原型继承的作用

————1)扩展内置对象
function MyArray(){
    //就可以在这里面添加你想添加的方法了(在下面继承了所有的Array属性和方法)
}
MyArray.prototype= [];
var NewArray=new MyArray();
NewArray.push(1);
NewArray.push(2,3,4);
alert(NewArray);

三、多态

js中没有相应的体现,在强类型语言中比较常用。
简而言之,就是使用父类的变量接受子类的对象。

创建对象的方式

(1)对象字面量

缺陷:只能创建一次对象,复用性较差,如果创建多个对象代码冗余度太高

var obj = {
    name: "字面量",
    type: "Object",

}

(2)使用构造函数

缺陷:想创建一个类似的对象,就会产生大量的代码

var box=new Object();
box.name='GJ';
box.age='18';
box.run=function() {
 return this.name+this.age+'运行中。。。'
}

(3)封装简单的工厂函数(不推荐使用)

它解决了重复实例化问题,但还有个识别问题,因为根本无法搞清楚他们到底是哪个对象的实例

function createBox(name,age) {
    var obj=new object();
    obj.name= name;
    obj.age=age;
    box.run=function() {
     return this.name+this.age+'运行中。。。'
    }
    return obj;
}
var obj = createBox('Gj',18);

(4)自定义构造函数

既解决了重复实例化的问题,又解决了对象识别的问题
默认返回的是新创建的对象,如果我们自己写的return语句,return的是空值或是基本数据类型,返回的都是新创建的对象;如果返回的是object类型的值,将取而代之

function Box(name,age) {
    this.name=name;
    this.age=age;
    this.run=function() {
         return this.name+this.age+'运行中。。。'
    }
}
var box1=new Box('GJ',100);
alert(box1.run());

(5)原型

  • 原型是什么?
    ——-在构造函数创建出来的时候,系统会默认的帮构造函数创建并关联一个原型
  • 原型可以用来做什么?
    ——-原型中的属性和方法可以被使用该构造函数创建出来的对象使用
  • 如何访问构造函数的原型
    ——-构造函数.prototype
  • 如何给原型对象添加属性和方法
    ——–使用对象的动态特性
    注意:当使用对象去访问属性和方法的时候,首先在对象自己内部查找,如果找到就直接使用,如果没有找到就用原型。
function Person(name,status) {
    this.name=name;
    this.status=status;
    this.act=function(){
        console.log("原型")
    }
}
var p = new Person("xyz","single");

Person.prototype.move = function() {
    console.log("我要做运动");
}
p.move();

(6)使用原型注意事项

  • 使用对象访问属性的时候,如果在本身内找不到就去原型中查找。但是使用点语法进行属性复值得时候并不会去原型中查找,对象中不存在该属性,就会给该对象新增该属性,如果在对象中有这个属性,修改这个属性
  • 如果在原型中的属性是引用类型的属性,那么所有的对共享该属性,并且一个对象修改了该引用类型属性中的成员,则其他所有跟这个原型对象相关的对象都会受到影响
  • 一般情况下原型中只会放需要共享的方法。

(7)原型链

1.什么是原型链?
    每个构造函数都有原型对象
    每个对象都会有构造函数
    每个构造函数的原型都是一个对象
    那么这个原型对象也会有构造函数
    那么这个原型对象的构造函数也会有原型对象
    这样就会形成一个链式的结构,称为原型链
2.原型链结构的基本形式
function Person(name){
    this.name=name;
}
var w=new Person();

//p ---> Person.prototype --->Object.prototype---->null

属性搜索的原则
——1.当访问一个对象的成员的时候,会先在自身找有没有,如果找到直接使用,
——2.如果没有找到,则去当前对象的原型对象中去查找,如果找到了直接使用,
——3.如果没有找到,继续找原型对象的原型对象,如果找到了,直接使用
——4.如果没有找到,则继续向上查找,直到Object.prototype,如果还是没有,就报错

(8) Object.prototype常用成员

成员 描述
Object.prototype.proto 指向当对象被实例化的时候,用作原型的对象。
Object.prototype.hasOwnProperty() 返回一个布尔值 ,表示某个对象是否含有指定的属性,而且此属性非原型链继承的。
Object.prototype.isPrototypeOf() 返回一个布尔值,表示指定的对象是否在本对象的原型链中。
Object.prototype.toString() 返回对象的字符串表示。
Object.prototype.valueOf() 返回指定对象的原始值。

补充

一. function的使用

(一)语法

———– Function函数所有的参数全都是字符串
———– Function函数的作用就是将所有的参数组合起来,变成一个函数
———– 1、如果只传一个参数,那么这个函数必然是函数体
———– 2、如果传多个参数,那么最后一个参数表示函数体,前面的参数代表将要创建的函数的参数
———– 3、如果不传参数,表示创建一个空函数

// 练习: 利用 Function 创建一个求三个数中最大数的函数.
var max = new Function("a", "b", "c", "return (a > b ? a : b)> c ? (a > b? a : b):c;");

(二)怎么解决function中代码过长问题

1.可以使用字符串拼接 让代码换行

 var max = new Function("arr",
         "var maxNum = arr[0];" +
         "for(var i = 1;i +
         "if(maxNum < arr[i]){" +
         "maxNum = arr[i];" +
         "}" +
         "}" +
         "return maxNum;"
 )

 console.log(max([1, 2, 3, 44, 5, 6]));

2.使用模板的方式,将代码写在模板标签内,获取该标签的内容

 window.onload =function () {
     var script = document.getElementById("funcContent");
     var str = script.innerHTML;
     var max = new Function("arr", str);
     console.log(max([1, 2, 3, 44, 5, 6]));
 }

 

3.使用反引号(`) 引住字符串,那么就可以 换行了

ES6 语法(很少有浏览器实现) 使用键盘左上角的` 表示可换行字符串的界定符,之前我们用的是单引号或者双引号来表示一个字符串字面量,在ES6中可以用反引号来表示该字符串可换行。

//这是es6中的语法,存在兼容性问题

 var str = `adfafdsa
            asdfas`;

        console.log(str);

(三)function和eval的区别

首先来说下eval
eval函数可以用来将字符串转换成JavaScript代码并且运行
var str = “var a = 10”;
eval(str);
console.log(a);
使用eval来解析JSON格式字符串的时候,会将{}解析为代码块,而不是对象的字面量,解决办法是:
1.在JSON格式的字符串前面拼接上 “var o =”
2.把JSON格式的字符串使用()括起来,就不会将{}解析为代码块,而是表达式

var jsonData = '({"name":"zs", "age":18})';
  var o = JSON.parse(jsonData);
     console.log(o);

eval("var o = "+ jsonData);
var o = eval(jsonData);
console.log(o);

1.共同点:都可以将字符串转换成js代码
2.不同点:
1)function创建出来的是函数并不会直接调用,只有当手动去调用才可以执行
2)eval把字符串转成代码之后,直接就执行

(四)arguments

函数内部的一个对象,在函数调用的时候,默认的会将所有传入的实参依次存入该对象(一个伪数组)
arguments.length:可以用来表示传入的实参的个数

(五)静态成员和实例成员

静态成员:是指构造函数的属性和方法
实例成员:是指实例的属性和方法

function Person(){
    this.name = "zs",
    this.sayHello = function(){
        console.log("Hello World");
    }
}

//下面这个sayHi方法就是构造函数自己的方法,也就是静态方法
Person.sayHi = function(){
    console.log("I'm a Person");
}

//原型属性属于构造函数,所以原型属性是静态属性
Person.prototype = {};
var p = new Person();

//这里的name是构造函数创建出来的实例对象的属性,所以是实例属性
p.name = "GJ";


//这里的sayHello也是构造函数创建出来的实例对象的方法,所以是实例方法
p.sayHello();


//在jQuery中,$("#id")是一个实例,所以它们都是实例成员
$("#id").css();
$("#id").text();

//像这种是jQuery内部的工具方法,属于静态方法
$.trim();
$.each();
$.extend();

//把工具方法,作为静态成员
//把跟对象相关的方法,作为实例成员

前端小白:所记内容有什么不对或是要完善的地方还望指出,感激不尽
小Tip:后期还会进行修改和补充

你可能感兴趣的:(Javascript)