精华内容
下载资源
问答
  • 如下所示: 代码如下: var person = new Object(); person.name = “Nicholas”; person.age = “29” person.job = “Software Engineer”; person.sayName = function () { alert(...早期的JavaScript开发人员
  • 1.OC与JS交互在UIWebView中使用iOS 开发 Object-C和JavaScript交互详解之OC与JS交互在UIWebView中使用2. WKWebView的使用详解iOS开发 WKWebView的使用3.OC与JS交互在WKWebView中使用// // ViewController.m // oc与...

    1.OC与JS交互在UIWebView中使用

    iOS 开发 Object-C和JavaScript交互详解之OC与JS交互在UIWebView中使用

    2. WKWebView的使用详解

    iOS开发 WKWebView的使用

    3.OC与JS交互在WKWebView中使用

    这里写图片描述

    //
    //  ViewController.m
    //  oc与js交互WKWebView
    //
    //  Created by zhouyu on 15/6/17.
    //  Copyright © 2015年 zhouyu. All rights reserved.
    //
    
    #import "ViewController.h"
    #import <WebKit/WebKit.h>
    #import "TestViewController.h"
    
    @interface ViewController () <WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler>
    /**
     *  webView
     */
    @property (nonatomic, strong) WKWebView *webView;
    /**
     *  进度条
     */
    @property (nonatomic, strong) UIProgressView *progress;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.navigationItem.title = @"oc与js交互";
    
        WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 10, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-64)];
        [self.view addSubview:webView];
        self.webView = webView;
    
        // 展示进度
        self.progress = [[UIProgressView alloc] init];
        self.progress.frame = CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, 10);
        [self.view addSubview:self.progress];
        self.progress.progress = 0;
    
        webView.navigationDelegate = self;
        // 添加监听
        [webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    
        NSURL *URL = [NSURL URLWithString:@"http://m.dianping.com/tuan/deal/5501525"];
        NSURLRequest *request = [NSURLRequest requestWithURL:URL];
        [webView loadRequest:request];
    
    }
    
    #pragma mark - 监听进度
    // 计算wkWebView进度条
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    
        if (object == self.webView && [keyPath isEqualToString:@"estimatedProgress"]) {
            CGFloat newprogress = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
            NSLog(@"进度 %f",newprogress);
    
            if (newprogress != 1.000000) {
                // 网页加载时就展示进度
                self.progress.hidden = NO;
                self.progress.progress = newprogress;
                self.webView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
            } else {
                // 网页加载完成就进度
                self.progress.hidden = YES;
            }
        }
    }
    
    // 记得取消监听
    - (void)dealloc {
        [self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
    }
    
    #pragma mark - WKNavigationDelegate
    // 在发送请求之前,决定是否跳转,是否决定继续加载这个网页
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
        NSLog(@"在发送请求之前,决定是否跳转 decidePolicyForNavigationAction");
    
        NSString *URLString = navigationAction.request.URL.absoluteString;
    //    NSLog(@"监测到的WKWebView上的请求 %@",URLString);
    
        NSRange range = [URLString rangeOfString:@"hm://"];
        if (range.length > 0) {
    
            // 控制器的跳转
            [self.navigationController pushViewController:[[TestViewController alloc] init] animated:YES];
    
            // 不允许跳转,即不加载这个链接对应的内容
            decisionHandler(WKNavigationActionPolicyCancel);
        } else {
            // 允许跳转,即加载这个链接对应的内容
            decisionHandler(WKNavigationActionPolicyAllow);
        }
    }
    
    // 页面开始加载时调用
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
        NSLog(@"页面开始加载时调用 didStartProvisionalNavigation");
    }
    
    // 在收到响应后,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
        NSLog(@"在收到响应后,决定是否跳转 decidePolicyForNavigationResponse");
    
        // 允许跳转,即继续加载这个链接对应的内容
        decisionHandler(WKNavigationResponsePolicyAllow);
    
        // 不允许跳转,即不再继续加载这个链接对应的内容
    //    decisionHandler(WKNavigationResponsePolicyCancel);
    }
    
    // 当内容开始返回时调用
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
        NSLog(@"当内容开始返回时调用 didCommitNavigation");
    }
    
    // 页面加载完成之后调用
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
        // 拼接JS的代码
        NSMutableString *JSStringM = [NSMutableString string];
    
        // 删除导航
        [JSStringM appendString:@"var headerTag = document.getElementsByTagName('header')[0];headerTag.parentNode.removeChild(headerTag);"];
        // 删除底部悬停按钮
        [JSStringM appendString:@"var footerBtnTag = document.getElementsByClassName('footer-btn-fix')[0]; footerBtnTag.parentNode.removeChild(footerBtnTag);"];
        // 删除底部布局
        [JSStringM appendString:@"var footerTag = document.getElementsByClassName('footer')[0]; footerTag.parentNode.removeChild(footerTag);"];
    
        // 给标签添加点击事件
        [JSStringM appendString:@"var figureTag = document.getElementsByTagName('figure')[0].children[0]; figureTag.onclick = function(){window.location.href = 'hm://?src='+this.src};"];
    
    //    [JSStringM appendString:@"var figureTag = document.getElementsByTagName('figure')[0].children[0]; figureTag.onclick = function(){window.location.href = 'headerimageclick://www.yaowoya.com};"];
    
        // OC调用JS代码
        [webView evaluateJavaScript:JSStringM completionHandler:nil];
    }
    
    // 页面加载失败时调用
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation {
        NSLog(@"页面加载失败时调用 didFailProvisionalNavigation");
    }

    4.使用拓展

    配置Js与Web内容交互
    WKUserContentController是用于给JS注入对象的,注入对象后,JS端就可以使用:

    window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

    来调用发送数据给iOS端,比如:

    window.webkit.messageHandlers.AppModel.postMessage({body: '传数据'});

    AppModel就是我们要注入的名称,注入以后,就可以在JS端调用了,传数据统一通过body传,可以是多种类型,只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型。

    下面我们配置给JS的main frame注入AppModel名称,对于JS端可就是对象了:

    // 通过JS与webview内容交互
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    
    config.userContentController = [[WKUserContentController alloc] init];
    
    // 注入JS对象名称AppModel,当JS通过AppModel来调用时,
    // 我们可以在WKScriptMessageHandler代理中接收到
    [config.userContentController addScriptMessageHandler:self name:@"AppModel"];

    当JS通过AppModel发送数据到iOS端时,会在代理中收到:

    #pragma mark - WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController
          didReceiveScriptMessage:(WKScriptMessage *)message {
      if ([message.name isEqualToString:@"AppModel"]) {
        // 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray,
        // NSDictionary, and NSNull类型
        NSLog(@"%@", message.body);
      }
    }

    5.配置代理

    如果需要处理web导航条上的代理处理,比如链接是否可以跳转或者如何跳转,需要设置代理;而如果需要与在JS调用alert、confirm、prompt函数时,通过JS原生来处理,而不是调用JS的alert、confirm、prompt函数,那么需要设置UIDelegate,在得到响应后可以将结果反馈到JS端:

    // 导航代理
    self.webView.navigationDelegate = self;
    // 与webview UI交互代理
    self.webView.UIDelegate = self;

    添加对WKWebView属性的监听

    WKWebView有好多个支持KVO的属性,这里只是监听loading、title、estimatedProgress属性,分别用于判断是否正在加载、获取页面标题、当前页面载入进度:

    // 添加KVO监听
    [self.webView addObserver:self
                 forKeyPath:@"loading"
                    options:NSKeyValueObservingOptionNew
                    context:nil];
    [self.webView addObserver:self
                 forKeyPath:@"title"
                    options:NSKeyValueObservingOptionNew
                    context:nil];
    [self.webView addObserver:self
                 forKeyPath:@"estimatedProgress"
                    options:NSKeyValueObservingOptionNew
                    context:nil];

    然后我们就可以实现KVO处理方法,在loading完成时,可以注入一些JS到web中。这里只是简单地执行一段web中的JS函数:

    #pragma mark - KVO
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary<NSString *,id> *)change
                           context:(void *)context {
      if ([keyPath isEqualToString:@"loading"]) {
        NSLog(@"loading");
      } else if ([keyPath isEqualToString:@"title"]) {
        self.title = self.webView.title;
      } else if ([keyPath isEqualToString:@"estimatedProgress"]) {
        NSLog(@"progress: %f", self.webView.estimatedProgress);
        self.progressView.progress = self.webView.estimatedProgress;
      }
    
      // 加载完成
      if (!self.webView.loading) {
        // 手动调用JS代码
        // 每次页面完成都弹出来,大家可以在测试时再打开
        NSString *js = @"callJsAlert()";
        [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable response, NSError * _Nullable error) {
          NSLog(@"response: %@ error: %@", response, error);
          NSLog(@"call js alert by native");
        }];
    
        [UIView animateWithDuration:0.5 animations:^{
          self.progressView.alpha = 0;
        }];
      }
    }

    6.WKUIDelegate

    与JS原生的alert、confirm、prompt交互,将弹出来的实际上是我们原生的窗口,而不是JS的。在得到数据后,由原生传回到JS:

    #pragma mark - WKUIDelegate
    - (void)webViewDidClose:(WKWebView *)webView {
         NSLog(@"%s", __FUNCTION__);
    }
    
    // 在JS端调用alert函数时,会触发此代理方法。
    // JS端调用alert时所传的数据可以通过message拿到
    // 在原生得到结果后,需要回调JS,是通过completionHandler回调
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
      NSLog(@"%s", __FUNCTION__);
      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:@"JS调用alert" preferredStyle:UIAlertControllerStyleAlert];
      [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
      }]];
    
      [self presentViewController:alert animated:YES completion:NULL];
      NSLog(@"%@", message);
    }
    
    // JS端调用confirm函数时,会触发此方法
    // 通过message可以拿到JS端所传的数据
    // 在iOS端显示原生alert得到YES/NO后
    // 通过completionHandler回调给JS端
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {
      NSLog(@"%s", __FUNCTION__);
    
      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"confirm" message:@"JS调用confirm" preferredStyle:UIAlertControllerStyleAlert];
      [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
      }]];
      [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
      }]];
      [self presentViewController:alert animated:YES completion:NULL];
    
      NSLog(@"%@", message);
    }
    
    // JS端调用prompt函数时,会触发此方法
    // 要求输入一段文本
    // 在原生输入得到文本内容后,通过completionHandler回调给JS
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler {
      NSLog(@"%s", __FUNCTION__);
    
      NSLog(@"%@", prompt);
      UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"textinput" message:@"JS调用输入框" preferredStyle:UIAlertControllerStyleAlert];
      [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.textColor = [UIColor redColor];
      }];
    
      [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler([[alert.textFields lastObject] text]);
      }]];
    
      [self presentViewController:alert animated:YES completion:NULL];
    }
    
    展开全文
  • 1. 原型链 ...[] -> Array.prototype -> Object.prototype -> null p -> Person.prototype -> Object.prototype -> null {} -> Object.prototype -> null 原型式继承: ① 原型


    1. 原型链
    (1)对象的原型链
    绘制原型链的结构(三角形)
    [] -> Array.prototype -> Object.prototype -> null
    p -> Person.prototype -> Object.prototype -> null
    {} -> Object.prototype -> null

    原型式继承
    ①  原型式继承就是原型中提供的成员,我们的实例对象可以直接使用,好像是自己的一样
    ② 所谓的 操作原型式继承就是在对原型链做增加、删除、修改的操作
    //如果有 animal
    function Person() {}
    Person.prototype = animal;
    var p = new Person();
    //原型链(相当于在原来的链中增加了一节):
    p -> Person.prototype(其实是animal) -> Animal.prototype -> Object.prototype

    (2)函数的原型链
    绘制原型链的结构

    (3)完整原型链
    结合对象的原型链和函数的原型链,将其绘制到一起

    2. Function

    Function 是函数的构造函数
    (函数的constructor属性就等于Function)
    借助这个理论可以绘制函数的对象原型链(三角形)


    3. 利用 Function 构建函数

    定义一个函数需要有:
    ① 参数
    ② 函数体
    ③ 返回值
     这三个东西本质上是代码,js允许将这些代码以字符串的形式放到 Function 中,来构建函数。
    语法:
    var func = new Function( 参数1, 参数2, ..., 函数体 )

    例:设计一个函数,求两个数字的和
    var sum = new Function( 'a', 'b', 'return a+b;' );

    函数体太多内容时,一般来说使用字符串拼接 + 折行显示。
    为了解决麻烦,引入ES6中的可换行字符串,数字键左边的左撇号。
    第三种方法,在页面添加一个标签
    <script type="text/template" id="code">
        函数体
    </script>






    document.createElementFragment
    应用:所见即所得的编辑器

    4. 绘制函数的原型链结构

    函数的构造函数是 Function
    Function 是什么数据类型?函数
    结论: Function 是 Function 的构造函数
    ① Function.prototype 是原型对象,Function 就继承自该原型对象
    ② Function 是 Function 的实例
    Function instanceof Function 为 true
    推论:
    Function instanceof Object 为 true
    Object instanceof Function 为 true


    Function 也是函数,因此 Function 是 Function 的实例
    这是原型链中唯一的特例(两个对象构成三角形关系)
    因此,Function 的 .prototype 与 .__proto__ 指向同一个对象


    一般的函数不是这样
    function Person() {}
    1) Person.prototype 是用于描述实例对象的, 表示 new Person() 所继承的对象. 
    2) Person.__proto__ 是用于描述 Person 这个函数作为对象来说是 Function 的实例. 是 Function.prototype. 
    因此一般的函数, 这两个属性不是同一个对象.

    Function -> Function.prototype -> Object.prototype -> null

    例如:希望让js中的所有函数都有 inherit 方法,来实现派生
    Function.prototype.inherit = function() {}
    Object.prototype.inherit = function() {}

    5. __proto__

    作用:让实例对象可以访问到该原型对象
    早期是无法直接访问的,如果早期需要访问,用 obj.constructor.prototype
    这样不方便调试,很麻烦,因此在火狐中率先引入 __proto__ 属性,用于让对象直接访问其原型。由于当时是非标准属性,因此使用__作为前后缀。但是由于非常好用,今天的浏览器基本都实现了该属性,但依旧没有标准化(IE8不支持)。因此在开发时,不建议用,也不可以使用该属性。
    调试原型链结构:obj.__protp__.__proto__.__proto__.__proto__
    因此在实际开发中,使用 __proto__ 只是用于调试查看,即只用其读的特性。

    以前的结论:
    ① 只有函数有 prototype 属性
    ② 只有实例对象有 __proto__ 属性

    今天的结论:函数也是对象,函数也有 __proto__ 属性
    ① 函数有 prototype 属性,该属性指向原型,该原型被函数的实例对象所继承
    ② 函数有 __proto__ 属性,该属性指向原型,该函数继承自该原型
    ③ 函数的 __proto__ 就是 Function.prototype,Function.__proto__ 就是 Function.prototype



    6. Object 本身就是一个构造函数

    function Person() { }
    // Object 与 Person 是等同地位的
    就像人是由基因决定的,无论是父亲还是儿子都有基因
    基因就好比构造函数,决定对象有什么成员,也就是对象长什么样子

    结论:
    ① 对象应该都有原型
    ② 实例对象继承自 构造函数.prototype
    ③ 原型对象也有继承的关系
    ④ 只有原型中有 constructor,constructor 决定了原型的名字
    如果 constructor 是 AAA, 那么 这个原型就是 AAA.prototype

    到此我们得到对象的原型链结构
    1) [ ]
        [ ] -> Array.prototype -> Object.prototype -> null
    2) p: Person
        p -> Person.prototype -> Object.prototype -> null
    3) { }
        { } -> Object.prototype -> null

    结合原型式继承. 什么是原型式继承? 怎么操作原型式继承?
    1) 原型式继承就是 原型中提供的成员, 我们的实例对象可以直接使用, 好像是自己的一样.
    2) 所谓的操作原型式继承就是在 对原型链做增加, 删除, 修改的操作.
    //如果有 animal
    function Person () {}
    Person.prototype = animal;
    var p = new Person();
    ...
    //原型链:
    //p -> Person.prototype( 其实是 animal ) -> Animal.prototype -> Object.prototype -> null

    7. 字面量的原型链

    所谓的字面量就是在代码中的写出来以后有数据、有大小、有类型等具体的数据。
    常见的字面量有:
    数字    1,2,123, ...
    布尔值    true,false
    字符串    'xxxxxx'
    对象    { },注意有时需要使用( { } )
    数组    [ ]
    函数    function() { }
    正则表达式    /.+/
    字面量中,凡是引用类型的都有对应的构造函数,因此原型链的绘制就简单了。



    8. 属性搜索原则
    错误的结论:如果一个对象中没有对应的方法,但是其原型中提供了该方法,该对象可以直接使用原型中的方法,就好像是自己的方法一样。

    所谓的属性搜索原则是说,对象在访问某一个成员的时候,采用的访问规则
    ① 首先在当前对象中查找是否有对应的成员(在自己的代码结构中找)
    ② 如果有,则使用该成员,并停止查找,如果没有,则到其原型对象中查找对应的成员
    ③ 如果其原型中有该成员,则使用,并停止查找,否则继续往原型的原型中查找
    ④ 如此往复
    ⑤ 直到 Object.prototype 中,如果还没有对应的成员,则返回 undefined

    访问依照 就近原则


    9. 原型成员的读写

    在读取数据的时候,如果当前对象没有该数据,原型中提供了该数据,那么可以直接访问该数据。但是,如果是修改属性,不会对原型中的数据造成任何影响,只会在当前对象中新创建一个该成员,再次读取该成员时,就不再走原型上的数据了。


    10. instanceof 运算符

    语法: object(要检测的对象) instanceof constructor(某个构造函数)  -> boolean
    含义:检测 constructor.prototype 是否存在于 object 的原型链上,即一个对象在其原型链中是否存在一个构造函数的 prototype 属性

    案例1:
    function Person() {}
    var p = new Person();
    p instanceof Person   // true
    //p 的原型链:
    //p -> Person.prototype -> Object.prototype -> null

    案例2:
    function Person() {}
    var p1 = new Person();
    Person.prototype = {};
    var p2 = new Person();
    console.log( p1 instanceof Person );//false
    console.log( p2 instanceof Person );//true
    //分析原型链:
    //p1 -> Person.prototype(原始的类型) -> Object.prototype -> null
    //p2 -> Person.prototype( { } ) -> Object.prototype -> null
    //现在 Person.prototype 是 { }
    //p1 instanceof Person 表示检测 { } 是否在 p1 的原型链中 -> false
    //p2 instanceof Person 表示检测 { } 是否在 p2 的原型链中 -> true



    案例3:
    console.log(Function instanceof Object);//true
    //Object.prototype 是否在 Function 的原型链中
    
    console.log(Function instanceof Function);//true
    //Function.prototype 是否在 Function 的原型链中
    
    console.log(Object instanceof Object);//true
    //Object.prototype 是否在 Object 的原型链中
    
    console.log(Object instanceof Function);//true
    //Function.prototype 是否在 Object 的原型链中
    //Object -> Function.prototype -> Object.prototype -> null

        Object、Function、Array 等等都是构造函数,都是函数 
    => 而所有函数都是构造函数 Function 的实例 
    => 从原型链机制来说,所有函数都能通过原型链找到创建他们的构造函数 Function 的构造原型 Function.prototype 对象
    => Object instanceof Function 的结果为 true

        又因为 Function.prototype 是一个对象
    => Function.prototype 的构造函数是 Object
    => 从原型链机制来说,所有对象都能通过原型链找到创建它们的构造函数 Object 的构造原型 Object.prototype 对象
    => Function instanceof Object 的结果为 true

        Function 是构造函数
    => Function 是函数对象
    => 函数对象都是由 Function 构造函数创建而来的,从原型链机制来说,函数对象的原型链中存在 Function.prototype 
    => Function.prototype 在构造函数 Function 的原型链中被查到
    => Function instanceof Function 的结果为 true

    结论:在 js 中,一切皆对象,它们全部继承自 Object,或者说所有对象的原型链的根节点都是 Object.prototype
    js原型链-jk.png

    11. Object.prototype 的常用成员

    (1)hasOwnProperty

    语法: 对象.hasOwnProperty( '属性名称' ) -> boolean
    含义:判断某个属性是否是当前对象提供,而不是原型提供的
    作用:一般在写混入的时候会使用
    for(var k in obj){
        //只混入当前对象的属性
        if(obj.hasOwnProperty(k)){
            dist[k] = obj[k];
        }
    }

    (2)isPrototypeOf

    语法: 对象A.isPrototypeOf( 对象B ) -> boolean
    含义:判断 对象A 是不是 对象B 的原型(实质上是判断对象A是否在对象B的原型链中)

    (3)prototypeIsEnumerable

    语法: 对象A.prototypeIsEnumerable(  '属性名称'  ) -> boolean
    含义:判断当前对象是否提供对应的属性,同时该属性可枚举
    在 js 中一般添加的成员都是可枚举的(所谓的可枚举就是利用 for in 可以遍历出来)
    在 ES5 之前,所有的自定义属性都是可枚举的,是无法控制的。因此该方法很少使用。
    在 ES5 之后,引入了 Object.definedPrototype 等方法,允许用户定义不可枚举的属性。

    (4)valueOf

    将对象转换成基本类型(实现的不好,平时不会用,都是自己实现该方法去转换)
    内部的实现就是 return this,把自己返回了,并没有实现功能,没什么用处

    (5)toString

    将对象转换成字符串(实现的不好,平时不会用,都是自己实现该方法去转换)
    console.log(s.toString());//[object Object](假设s是个对象)
    console.log([].toString());//默认将数组元素用逗号连接,因此会打印空
    //数组自己有 toString 方法

    (6)toLocaleString

    将对象转换成本地字符串(实现的不好,平时不会用,都是自己实现该方法去转换)
    例:


    计算机毫秒数从1970年开始算






    展开全文
  • JS高级开发-内置对象Object梳理

    千次阅读 热门讨论 2021-03-23 09:52:28
    JavaScript中,几乎所有的对象都是Object类型的实例,它们都会从Object.prototype继承属性和方法。Object构造函数为给定值创建一个对象包装器。Object构造函数,会根据给定的参数创建对象,具体有以下情况: 如果...

         Object 构造函数创建一个对象包装器。在JavaScript中,几乎所有的对象都是Object类型的实例,它们都会从Object.prototype继承属性和方法。Object构造函数为给定值创建一个对象包装器。Object构造函数,会根据给定的参数创建对象,具体有以下情况:

    • 如果给定值是null或undefined,将会创建并返回一个空对象。
    • 如果传进去的是一个基本类型的值,则会构造其包装类型的对象。
    • 如果传进去的是引用类型的值,仍然会返回这个值,经他们复制的变量保有和源对象相同的引用地址。

    当以非构造函数形式被调用时,Object的行为等同于new Object()。

    var obj1 = {name:"小张"};
    //等价于
    var obj2 = new Object(); 
    obj2.name = '小张';

    Object 构造函数的属性:

    Object.length:  值为1。

    Object.prototype:  可以为所有Object类型的对象添加属性。


    Object 构造函数的方法:

    Object.assign():  用于将所有可枚举属性的值从一个或多个源对象分配到目标对象并返回目标对象。Object.assign(target, ...sources),target为目标对象。

    Object.create():  使用指定的原型对象和属性创建一个新的对象。

    Object.create(proto,[propertiesObject])。

    • proto新创建对象的原型对象
    • propertiesObject可选,该对象的属性类型参照Object.defineProperties()的第二个参数。如果不为undefined,该传入对象的自有可枚举属性(即自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。如果propertiesObject参数是 null 或非原始包装对象,则抛出一个 TypeError 异常。

    Object.defineProperty():  给对象添加一个属性并指定该属性的配置。详细参考:地址 

    Object.defineProperty(obj, prop, descriptor)
    • obj: 要定义属性的对象
    • prop: 要定义或修改的属性的名称或Symbol
    • descriptor: 要定义或修改的属性描述符

    Object.defineProperties():  给对象添加多个属性并分别指定它们的配置。详细参考:地址 

    Object.entries():  返回给定对象自身可枚举属性的[key, value]数组。

    Object.keys():  返回一个包含所有给定对象自身可枚举属性名称的数组。

    Object.values(): 返回给定对象自身可枚举值的数组。

    Object.freeze():  冻结对象:其他代码不能删除或更改任何属性。

    Object.isFrozen(): 判断对象是否已经冻结。

    Object.isExtensible(): 判断对象是否可扩展。(针对[[prototype]]属性)

    Object.preventExtensions(): 防止对象的任何扩展。

    (下图第一张红色框内部分,注意看演示下图第2,3张图片Object.defineProperty()中在阻止扩展后修改configurable属性,未能删除对象obj中school的属性,原因是configurable属性扩展后修改后未发生改变(即扩展后[[prototype]]链上的属性除了value可以改变,其他不能修改))

    Object.seal(): 防止其他代码删除对象的属性。封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

    Object.isSealed(): 判断对象是否已经密封。

    Object.getOwnPropertyDescriptor(): 返回对象指定的属性配置。

    Object.getOwnPropertyNames():  返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。

    Object.getOwnPropertySymbols(): 返回一个数组,它包含了指定对象自身所有的符号属性。

    Object.is(): 比较两个值是否相同。所有NaN值都相等。(这与==和===不同)。

    Object.setPrototypeOf():  设置对象的原型(即内部[[Prototype]]属性)。Object.setPrototypeOf(obj, prototype)

    Object.getPrototypeOf(): 返回指定对象的原型对象。

    Object实例和Object原型对象:

            JavaScript中的所有对象都来自Object;所有对象从Object.prototype继承方法和属性,尽管它们可能被覆盖。例如,其他构造函数的原型将覆盖constructor属性并提供自己的toString()方法。Object原型对象的更改将传播到所有对象,除非受到这些更改的属性和方法将沿原型链进一步覆盖。

    属性

    Object.prototype.constructor(): 特定的函数,用于创建一个对象的原型。

    方法

    Object.prototype.hasOwnProperty():返回一个布尔值,表示某个对象是否包含指定的属性,而且此属性非原型链继承的。

    Object.prototype.isPrototypeOf(): 返回一个布尔值,表示指定的对象是否在本对象的原型链中。

    Object.prototype.propertyIsEnumerable(): 判断指定属性是否可枚举。

    Object.prototype.toString(): 返回对象的字符串表示。

    Object.prototype.toLocalString(): 直接调用toString()方法。

    Object.prototype.valueOf(): 返回指定对象的原始值。

     

     

    展开全文
  • 开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组...受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性添加或删除。由于 Vue 会在...

    在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。

    5e5663f59b044727.jpg

    根据官方文档定义:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

    受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

    看以下实例:

    {{obj.d}}

    {{obj.e}}

    export default {

    data(){

    return {

    obj:{}

    }

    },

    mounted() {

    this.obj = {d: 0};

    this.obj.e = 0;

    console.log('after--', this.obj);

    },

    methods: {

    addd(item) {

    item.d = item.d + 1;

    console.log('item--',item);

    },

    adde(item) {

    item.e = item.e + 1;

    console.log('item--',item);

    }

    }

    }

    1581910087845868.png

    可以看出d属性是有get 和 set方法的,而新增的e属性是没有的。

    点击触发3次addd,点击触发3次adde,页面效果及控制台信息如下

    1581910104472895.png

    1581910127936800.png

    此时触发1次addd,页面效果如下:

    1581910136829791.png

    1581910159111774.png

    由此可以看出,更新新增属性e,是不会更新视图,但是会改变其值,当更新原有属性d时会更新视图,同时将新增的属性e的值也更新到视图里边

    解决方案

    官方定义:

    Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上:Vue.set(vm.obj, 'e', 0)

    您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:this.$set(this.obj,'e',02)

    有时你想向已有对象上添加一些属性,例如使用 Object.assign() 或 _.extend() 方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性:// 代替 Object.assign(this.obj, { a: 1, e: 2 })

    this.obj= Object.assign({}, this.obj, { a: 1, e: 2 })

    上述实例解决如下:

    1581910240469349.png

    点击触发3次addd,点击触发3次adde,页面效果及控制台信息如下:

    1581910252950006.png

    1581910269441062.png

    更多web前端开发知识,请查阅 HTML中文网 !!

    展开全文
  • 该framework为OC与JS代码相互操作的提供了极大的便利。该工程默认是没有导入工程中的,需要我们手动添加添加完成后,我们可以看到JavaScriptCore.h中包含以下5个主要的文件。#import "JSContext.h" #import "JSVal
  • 5.1 JSObject类型

    2016-12-29 00:50:00
    1.Object类型是引用类型中的一种。 2.创建Object实例(对象)的方式: 方式1:使用new操作符,后面跟上Object...//给对象添加属性 obj.about = "JavaScript教程";// 给对象添加属性 方式2:对象字面量方式,...
  • 引言 在使用构造函数创建对象的时候使用的方法是:var test = new Object();实质上是在其“祖宗”上...使用方法:当我们在开发的过程中遇到一个对象,并不清楚其实那个函数创建的时候,可以调用constructor属性知...
  • 这篇博客是读You Dont Know JS系列书中this & Object Prototypes这本书后总结的第二篇博客(第一篇讲this到底是什么)。 这篇博客讲对象,其中会涉及到一些让我们困惑已久的问题,比如:对象的数据属性和访问器属性...
  • objective-c 动态添加属性

    千次阅读 2019-03-21 18:30:53
    项目开发中经常会申明变量保存相关相关值,但是对于功能太多的类中申明过多的变量看着就非常的繁琐,尤其是使用动态语言如javaScript 写过功能的都知道,动态语言可以动态的在一个对象上添加新的属性和值,这将是...
  • JS Object 详解

    千次阅读 2017-12-21 10:47:53
    Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的。虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是Object对象其实包含了很多很有用...
  • JS:Object 对象

    2019-12-24 23:14:36
    Object 对象,属于复合数据类型 对象的分类 1.内建对象 由ES标准中定义的对象,在任何ES的实现中都可以使用 比如:Math String Number Boolean 2.宿主对象 由JS运行的环境提供的对象,目前主要由浏览器...
  • 对于多数Web开发任务来说,选择Object还是Map只是个人偏好问题,影响不大。不过,对于在乎内存和性能的开发者来说,对象和映射之间确实存在显著的差别。 1.内存占用 Object和Map的工程级实现在不同浏览器间存在明显...
  • 实际开发中,有时需要知道对象的所有属性,原生js提供了一个方法Object.keys()。Object.keys(obj)返回的是一个数组,该数组的所有元素都是字符串。这些元素是来自于给定的obj可直接枚举的属性,这些属性的顺序与手动...
  • 【实现效果】 点击,对象轮廓变为绿色; 【代码】 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>...script src="https://cesiumjs....
  • 在程序运行时可以为JavaScript对象添加属性。 对象的属性可以使用索引运算符“[]”进行访问:对象名[“属性名”]; <body> <script type="text/javascript"> var person = new Object(); person....
  • 自ES5开始,js中的对象属性具有属性描述符。可以直接检测与定义属性特性。 检测属性特性: var obj = { a: 2 } console.log(Object.getOwnPropertyDescriptor(obj, 'a')); //打印 /** configurable: true ...
  • Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的。虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是Object对象其实包含了很多很有用...
  • JavaScript 对象和属性

    2016-08-10 09:15:21
    面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。...
  • javascript protype 属性

    2010-01-07 13:39:00
    函数(functions)在javascript中本身就是对象,它有方法和属性。关于函数的属性,prototype是比较重要的一个。Js代码 function foo(a,b){ return a*b;...//object 可以为prototype添加属性Js代码 foo.prototy
  • JavaScript prototype 属性

    2016-07-29 10:46:00
    prototype 属性使开发人员有能力向对象添加属性和方法。 语法 object.prototype.name=value 实例 在本例中,我们将展示如何使用 prototype 属性来向对象添加属性: <script type="text/javascript">...
  • 操作对象2.1 创建对象方式一方式二2.2 向对象中添加属性2.3 读取对象中的属性2.4 删除对象中的属性2.5 遍历2.6 使用对象字面量,在创建对象时直接向对象中添加属性3. 基本数据类型和引用数据类型的区别 对象...
  • 要说标题中的四种数据类型,先从js所有数据类型了解,JavaScript数据类型分两种: 基本数据类型(string / number / boolear / null / undefine)栈内存 引述数据类型(object / array / map / set / functio...
  • 开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,不会更新视图。 根据官方文档定义:如果在实例...
  • Javascript 对象属性CURD操作

    千次阅读 2020-04-30 14:55:09
    了解js对象的属性相关操作, 应用于开发中. 2.学习/操作 1.介绍 js中有句名言: 一切皆对象 在编程语言里, 相同点, 对象是存储数据的容器, 而且都常是使用{}来表示, 但是声明对象的方式有很多种, ...
  • 3.为自定义控件添加属性

    万次阅读 2014-03-28 20:04:32
    3.为自定义控件添加属性 原文请看我博客:http://clzf.co/blog.php?id=3 前面"废话"了两篇 现在开始慢慢的踏入自定义控件开发的主题 首先来说说属性 对于一个控件来说属性和事件什么的是必须的 要不然也没啥意义...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 103,267
精华内容 41,306
关键字:

js开发object添加属性